UNPKG

@jovian/type-tools

Version:

TypeTools is a Typescript library for providing extensible tooling runtime validations and type helpers.

1,179 lines 45.2 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); 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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }); exports.timerInterval = exports.TimerRegistrant = exports.Timer = exports.mainSharedTimer = exports.SharedTimer = exports.SharedTimerBlock = void 0; var ix_config_1 = require("./ix.config"); var ix_entity_1 = require("./ix.entity"); var prom_util_1 = require("./util/prom.util"); var SharedTimerBlock = (function (_super) { __extends(SharedTimerBlock, _super); function SharedTimerBlock(init) { var _this = _super.call(this, 'timerblock') || this; _this.name = ''; _this.active = true; _this.started = false; _this.startTime = 0; _this.maxBlocks = 10000; _this.blockMs = 1; _this.procCount = 1; _this.procInterval = 1; _this.lastRegister = 0; _this.pendingCount = 0; _this.notMsBlock = false; _this.procs = []; _this.immediates = []; _this.timeblock = []; _this.timeblockCursor = 0; _this.maxMs = _this.maxBlocks * _this.blockMs; _this.last = 0; _this.totalHandledBlocksCount = 0; if (init) { Object.assign(_this, init); } _this.addOnDestroy(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { this.clearAllProcs(); return [2]; }); }); }); _this.maxMs = _this.maxBlocks * _this.blockMs; _this.notMsBlock = (_this.blockMs > 1); return _this; } Object.defineProperty(SharedTimerBlock.prototype, "maxSupportedMs", { get: function () { return this.maxMs; }, enumerable: false, configurable: true }); Object.defineProperty(SharedTimerBlock.prototype, "totalHandledBlocks", { get: function () { return this.totalHandledBlocksCount; }, enumerable: false, configurable: true }); SharedTimerBlock.prototype.clearAllProcs = function () { this.checkingLogic(true); for (var _i = 0, _a = this.procs; _i < _a.length; _i++) { var proc = _a[_i]; clearInterval(proc); } }; SharedTimerBlock.prototype.setImmediate = function (reg) { if (!reg.regStart) { reg.regStart = Date.now(); } if (!this.replacedBy) { var now = Date.now(); this.lastRegister = now; this.immediates.push({ reg: reg }); } else { this.getReplacement().setImmediate(reg); } }; SharedTimerBlock.prototype.getReplacement = function () { var rpl = this.replacedBy; while (rpl.replacedBy) { rpl = rpl.replacedBy; } return rpl; }; SharedTimerBlock.prototype.setImmediateOnce = function (reg) { if (!reg.regStart) { reg.regStart = Date.now(); } if (!this.controller.started) { this.controller.startBlocks(); } if (!this.replacedBy) { var now = Date.now(); this.lastRegister = now; this.immediates.push({ reg: reg, once: true }); } else { var rpl = this.getReplacement(); rpl.immediates.push({ reg: reg, once: true }); } }; SharedTimerBlock.prototype.setIntoBlock = function (reg) { if (!this.replacedBy) { var now = Date.now(); this.lastRegister = now; ++this.pendingCount; if (this.notMsBlock) { var adjusted = reg.blockInterval; adjusted += this.timeblockCursor; while (adjusted >= this.timeblock.length) { adjusted -= this.timeblock.length; } var spot = this.timeblock[adjusted]; spot.push({ reg: reg }); reg.regSpot = spot; reg.regLast = now; } else { if (reg.nowait && reg.blockInterval > 0 && reg.regLast > 0) { var overflow = now - reg.regLast - reg.blockInterval + reg.regOverflow; var adjusted = reg.blockInterval - overflow; if (adjusted < 0) { adjusted = 0; } adjusted += this.timeblockCursor; while (adjusted >= this.timeblock.length) { adjusted -= this.timeblock.length; } var spot = this.timeblock[adjusted]; spot.push({ reg: reg }); reg.regSpot = spot; reg.regOverflow = overflow; } else { var adjusted = reg.blockInterval; adjusted += this.timeblockCursor; while (adjusted >= this.timeblock.length) { adjusted -= this.timeblock.length; } var spot = this.timeblock[reg.blockInterval]; spot.push({ reg: reg }); reg.regSpot = spot; reg.regLast = now; } } reg.regLast = now; reg.timerblock = this; reg.controller = this.controller; } else { this.getReplacement().setIntoBlock(reg); } }; SharedTimerBlock.prototype.register = function (reg) { if (!reg.regStart) { reg.regStart = Date.now(); } if (!this.controller.started) { this.controller.startBlocks(); } if (reg.immediate || reg.ms < 1) { this.controller.baseblock.setImmediate(reg); } else { if (!this.replacedBy) { this.setIntoBlock(reg); } else { this.getReplacement().setIntoBlock(reg); } } return reg; }; SharedTimerBlock.prototype.start = function () { var _this = this; if (this.started) { return; } this.started = true; this.startTime = Date.now(); this.last = Date.now(); this.timeblock.length = this.maxBlocks; for (var i = 0; i < this.maxBlocks; ++i) { this.timeblock[i] = []; } this.checkingLogic = function (immediatesOnly) { var now = Date.now(); var repeatersList = []; for (var j = 0; j < _this.immediates.length; ++j) { _this.handleRegistration(_this.immediates[j], now, repeatersList); } _this.immediates = []; _this.handlerRepeatersIfAny(repeatersList); if (immediatesOnly) { return; } var delta = now - _this.last; if (delta === 0) { return; } var rawDelta = _this.notMsBlock ? delta / _this.blockMs : delta; var blockCountToHandle = _this.notMsBlock ? Math.floor(delta / _this.blockMs) : delta; if (blockCountToHandle === 0) { return; } if (_this.notMsBlock) { var timeOvercounted = Math.round((rawDelta - blockCountToHandle) * _this.blockMs); _this.last = now - timeOvercounted; } else { _this.last = now; } if (_this.timeblock.length === 0) { _this.clearAllProcs(); return; } var blockCountToHandleSafe = Math.min(blockCountToHandle, _this.timeblock.length); for (var j = 0; j < blockCountToHandleSafe; ++j) { var index = _this.timeblockCursor + j; while (index >= _this.timeblock.length) { index -= _this.timeblock.length; } var ontheblock = _this.timeblock[index]; for (var _i = 0, ontheblock_1 = ontheblock; _i < ontheblock_1.length; _i++) { var streg = ontheblock_1[_i]; --_this.pendingCount; _this.handleRegistration(streg, now, repeatersList); } if (!_this.replacedBy) { _this.timeblock[index] = []; } else if (_this.timeblock.length === 0) { _this.clearAllProcs(); break; } } _this.timeblockCursor += blockCountToHandleSafe; while (_this.timeblockCursor >= _this.timeblock.length) { _this.timeblockCursor -= _this.timeblock.length; } _this.handlerRepeatersIfAny(repeatersList); _this.totalHandledBlocksCount += blockCountToHandleSafe; }; for (var i = 0; i < this.procCount; ++i) { this.procs.push(setInterval(this.checkingLogic, this.procInterval)); } }; SharedTimerBlock.prototype.handlerRepeatersIfAny = function (repeatersList) { if (repeatersList.length > 0) { for (var _i = 0, repeatersList_1 = repeatersList; _i < repeatersList_1.length; _i++) { var reg = repeatersList_1[_i]; reg.timerblock.setIntoBlock(reg); } repeatersList.length = 0; } }; SharedTimerBlock.prototype.handleRegistration = function (streg, now, repeatersList) { var _this = this; var _a, _b, _c; var reg = streg.reg; if (!reg.active) { return; } reg.last = now; if (!reg.paused && reg.skipCount === 0) { (_a = reg.pre) === null || _a === void 0 ? void 0 : _a.call(reg, reg); reg.callback(reg); var ibhKeys = reg.intervalBehavior ? Object.keys(reg.intervalBehavior) : null; if (ibhKeys && ibhKeys.length > 0) { for (var _i = 0, ibhKeys_1 = ibhKeys; _i < ibhKeys_1.length; _i++) { var ibhKey = ibhKeys_1[_i]; var bh = reg.intervalBehavior[ibhKey]; (_b = bh.callback) === null || _b === void 0 ? void 0 : _b.call(bh, bh, reg); } } (_c = reg.post) === null || _c === void 0 ? void 0 : _c.call(reg, reg); } if (reg.skipCount > 0) { --reg.skipCount; } if (reg.repeat) { if (!reg.waitBeforeRepeat) { repeatersList.push(reg); } else { ++this.pendingCount; reg.waitBeforeRepeat.then(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { if (reg.regSpot) { --this.pendingCount; } if (reg.active && reg.repeat) { reg.timerblock.setIntoBlock(reg); } return [2]; }); }); }); reg.waitBeforeRepeat = null; } } }; return SharedTimerBlock; }(ix_entity_1.Entity)); exports.SharedTimerBlock = SharedTimerBlock; var SharedTimer = (function (_super) { __extends(SharedTimer, _super); function SharedTimer(rubric) { var _this = _super.call(this, 'shared-timer') || this; _this.name = ''; _this.timerblocks = []; _this.started = false; _this.name = rubric.name; for (var _i = 0, _a = rubric.timerblocks; _i < _a.length; _i++) { var timerBlockConfig = _a[_i]; var timerblock = new SharedTimerBlock(timerBlockConfig); timerblock.controller = _this; timerblock.lcManagedBy(_this); _this.timerblocks.push(timerblock); } _this.baseblock = _this.timerblocks[0]; _this.addOnDestroy(function () { if (_this.checkerId) { clearInterval(_this.checkerId); } }); return _this; } SharedTimer.prototype.startBlocks = function () { if (this.started) { return this; } this.started = true; for (var _i = 0, _a = this.timerblocks; _i < _a.length; _i++) { var timerblock = _a[_i]; timerblock.start(); } return this; }; SharedTimer.prototype.endOnEmpty = function (checkingInterval) { var _this = this; if (checkingInterval === void 0) { checkingInterval = 200; } if (this.checkerId) { return this; } this.checkerId = setInterval(function () { var totalPending = 0; for (var _i = 0, _a = _this.timerblocks; _i < _a.length; _i++) { var timerblock = _a[_i]; totalPending += timerblock.pendingCount; } if (totalPending === 0) { _this.destroy(); } }, checkingInterval); return this; }; SharedTimer.prototype.setPrecision = function (level) { var procInterval = this.baseblock.procInterval; switch (level) { case 'max': procInterval = 0; break; case 'ultra': procInterval = 1; break; case 'super': procInterval = 2; break; case 'faster': procInterval = 5; break; case 'default': procInterval = 10; break; case 'slower': procInterval = 20; break; case 'lazy': procInterval = 33; break; case 'superlazy': procInterval = 50; break; case 'ultralazy': procInterval = 100; break; default: return; } if (this.baseblock.procInterval !== procInterval) { var oldBlock = this.baseblock; var newBlock = new SharedTimerBlock({ name: oldBlock.name, procInterval: procInterval, procCount: oldBlock.procCount, blockMs: oldBlock.blockMs, maxBlocks: oldBlock.maxBlocks, }); newBlock.controller = this; newBlock.replacing = oldBlock; newBlock.start(); oldBlock.replacedBy = newBlock; this.baseblock = this.timerblocks[0] = newBlock; } return this; }; return SharedTimer; }(ix_entity_1.Entity)); exports.SharedTimer = SharedTimer; exports.mainSharedTimer = new SharedTimer({ name: 'main', timerblocks: [ { name: 'up to 10s', procInterval: 1, blockMs: 1, maxBlocks: 10000 }, { name: 'up to 10m', procInterval: 200, blockMs: 100, maxBlocks: 6000 }, { name: 'up to 10h', procInterval: 1000, blockMs: 10000, maxBlocks: 3600 }, { name: 'up to 10d', procInterval: 1000, blockMs: 120000, maxBlocks: 7200 }, { name: 'up to 3mo', procInterval: 1000, blockMs: 10800000, maxBlocks: 720 }, ] }); exports.mainSharedTimer.addOnDestroy(function () { ix_config_1.ixConfig.sleepFunctions.useSharedTimer = false; }); var Timer = (function (_super) { __extends(Timer, _super); function Timer(spec, ontick) { var _this = _super.call(this, 'timer') || this; _this.name = ''; _this.maxCount = 1; _this.count = 0; _this.paused = false; _this.started = false; _this.ended = false; _this.finished = false; _this.startTime = -1; _this.endTime = -1; _this.finishTime = -1; _this.deltaEnd = -1; _this.deltaFinish = -1; _this.deltaEndFinish = -1; _this.lastTick = -1; _this.lastExec = -1; _this.autoDestroy = false; _this.result = null; _this.error = null; _this.reg = new TimerRegistrant({ source: _this }); _this.interval = 1000; _this.cond = null; _this.endResolves = []; _this.finishResolves = []; _this.lingeringLogic = {}; _this.endOnResult = false; _this.executing = false; if (!spec) { spec = {}; } if (typeof spec === 'number') { spec = { ms: spec }; } _this.options = spec; _this.ontick = ontick ? ontick : function () { }; _this.interval = _this.fromUnit(_this.options); if (_this.interval <= 0) { _this.interval = 1000; } _this.name = _this.options.name ? _this.options.name : "(timer-".concat(_this.ixId, ")"); _this.addOnDestroy(function () { _this.end(); }); if (_this.options.count !== null && _this.options.count !== undefined) { _this.maxCount = _this.options.count; } if (_this.options.forever) { _this.maxCount = 0; } if (!_this.options.defer) { var startNow = _this.options.immediately || _this.options.startNow; _this.nudge(startNow ? { immediately: true } : null); } return _this; } Object.defineProperty(Timer.prototype, "ordinal", { get: function () { return this.count + 1; }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "nth", { get: function () { return this.count + 1; }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "elapsed", { get: function () { return this.startTime < 0 ? 0 : Date.now() - this.startTime; }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "now", { get: function () { return Date.now(); }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "endPromise", { get: function () { var _this = this; return new Promise(function (resolve) { return _this.ended ? resolve(_this) : _this.endResolves.push(resolve); }); }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "finishPromise", { get: function () { var _this = this; return new Promise(function (resolve) { return _this.finished ? resolve(_this) : _this.finishResolves.push(resolve); }); }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "beforetick$", { get: function () { return this.ixRx('beforetick').obs(); }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "tick$", { get: function () { return this.ixRx('tick').obs(); }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "aftertick$", { get: function () { return this.ixRx('aftertick').obs(); }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "end$", { get: function () { return this.ixRx('end').obs(); }, enumerable: false, configurable: true }); Object.defineProperty(Timer.prototype, "finish$", { get: function () { return this.ixRx('finish').obs(); }, enumerable: false, configurable: true }); Timer.prototype.asPromise = function () { return this.finishPromise; }; Timer.prototype.runOnce = function () { var _this = this; if (this.ended) { return null; } this.lastTick = Date.now(); if (this.startTime < 0) { this.started = true; this.startTime = Date.now(); } if (this.paused) { return null; } var isPromise = false; var e = this.getSnapshot(''); var preCondPassed = (this.cond !== false && this.cond === null || this.cond === true || (this.cond && this.cond(this))); if (preCondPassed && this.maxCount === 0 || this.count < this.maxCount) { e.context = 'beforetick'; this.ixRx('beforetick').next(e); try { this.executing = true; this.lastExec = Date.now(); e.context = 'main'; var res = this.ontick(e); isPromise = (res && res.then); if (isPromise) { var iterId_1 = this.count + ''; var iterProm = this.execProm = res; this.lingeringLogic[iterId_1] = iterProm; iterProm.then(function (r) { _this.executing = false; _this.result = e.result = r; _this.error = e.error = null; if (_this.lingeringLogic[iterId_1]) { delete _this.lingeringLogic[iterId_1]; } e.context = 'aftertick-async'; _this.ixRx('aftertick').next(e); if (_this.result && _this.endOnResult) { _this.end(); } _this.detectStopCond(); }).catch(function (error) { _this.executing = false; _this.result = e.result = null; _this.error = e.error = error; if (_this.lingeringLogic[iterId_1]) { delete _this.lingeringLogic[iterId_1]; } e.context = 'main-error-async'; _this.ixError(error, null, e); e.context = 'aftertick-async'; _this.ixRx('aftertick').next(e); _this.detectStopCond(); }); } else { this.executing = false; this.result = e.result = res; this.error = e.error = null; } } catch (error) { this.executing = false; this.error = e.error = error; } if (!e.error) { e.context = 'tick'; this.ixRx('tick').next(e); } else { e.context = 'main-error'; this.ixError(e.error, null, e); } if (!isPromise) { e.context = 'aftertick'; this.ixRx('aftertick').next(e); } this.count += 1; if (this.result && this.endOnResult) { this.end(); } } if (!isPromise) { this.detectStopCond(); } return isPromise ? this.execProm : null; }; Timer.prototype.start = function () { var _this = this; var _a, _b; if (this.started) { return this; } this.started = true; this.startTime = Date.now(); this.reg.nowait = !!this.options.nowait; this.reg.update({ immediate: !!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.immediately) || ((_b = this.options) === null || _b === void 0 ? void 0 : _b.startNow)), ms: this.interval, repeat: true, callback: function (reg) { var res = _this.runOnce(); var needToWait = _this.executing && !_this.options.nowait; if (res && res.then && needToWait) { reg.waitBeforeRepeat = res; } } }); this.reg.registerOn(exports.mainSharedTimer); return this; }; Timer.prototype.immediate = function () { this.options.startNow = this.options.immediately = true; return this; }; Timer.prototype.pause = function () { this.paused = true; return this; }; Timer.prototype.resume = function () { this.paused = false; return this; }; Timer.prototype.nudge = function (options, beforenudge) { var _this = this; if (options === null || options === void 0 ? void 0 : options.immediately) { this.options.immediately = true; } if (!this.started) { (0, prom_util_1.promise)(function (resolve) { return setTimeout(resolve, 0); }).then(function () { if (beforenudge) { beforenudge(); } _this.start(); }); } return this; }; Timer.prototype.watch = function (ms, onwatchtick) { var _this = this; if (!ms) { ms = 1000; } if (onwatchtick) { this.onwatchtick = onwatchtick; } this.startRegCondCheck(ms); this.regWatch.callback = function () { if (_this.onwatchtick) { _this.onwatchtick(_this); } if (_this.cond && typeof _this.cond !== 'boolean') { var passed = _this.cond(_this); if (!passed) { _this.end(); } } }; this.regWatch.registerOn(exports.mainSharedTimer); this.regWatch.updateInterval(ms); return this; }; Timer.prototype.attend = function (level, onwatchtick) { if (level === void 0) { level = 'default'; } switch (level) { case 'hyper': return this.watch(1, onwatchtick); case 'super': return this.watch(10, onwatchtick); case 'vigilant': return this.watch(100, onwatchtick); case 'default': return this.watch(null, onwatchtick); case 'lazy': return this.watch(1000, onwatchtick); case 'lazier': return this.watch(10001, onwatchtick); case 'superlazy': return this.watch(60000, onwatchtick); case 'ultralazy': return this.watch(600000, onwatchtick); default: return this; } }; Timer.prototype.stop = function () { return this.end(); }; Timer.prototype.end = function () { var _this = this; if (this.ended) { return this; } if (this.startTime < 0) { this.started = true; this.startTime = Date.now(); } this.ended = true; this.endTime = Date.now(); this.deltaEnd = this.endTime - this.startTime; if (this.reg) { this.reg.invalidate(); } if (this.regWatch) { this.regWatch.invalidate(); } this.ixRx('end').next(this); for (var _i = 0, _a = this.endResolves; _i < _a.length; _i++) { var resolve = _a[_i]; try { resolve(this); } catch (error) { var e = this.getSnapshot('end-error'); e.error = error; this.ixError(error, 1, e); } } var lingerIterationsKeys = Object.keys(this.lingeringLogic); var finishingNow = (this.options.endSharp || lingerIterationsKeys.length === 0); if (finishingNow) { this.finishingWrapUp(); } else { var lingeringProms = lingerIterationsKeys.map(function (key) { return _this.lingeringLogic[key]; }); prom_util_1.PromUtil.allSettled(lingeringProms).then(function () { _this.finishingWrapUp(); }); } return this; }; Timer.prototype.forever = function () { this.maxCount = 0; this.nudge(); return this; }; Timer.prototype.nowAndForever = function () { this.maxCount = 0; this.nudge({ immediately: true }); return this; }; Timer.prototype.countUp = function (count) { if (count <= 0 || !Number.isFinite(count)) { throw new Error("'count' argument of value '".concat(count, " is not valid'")); } this.maxCount = count; this.nudge(); return this; }; Timer.prototype.countUpNow = function (count) { if (count <= 0 || !Number.isFinite(count)) { throw new Error("'count' argument of value '".concat(count, " is not valid'")); } this.maxCount = count; this.nudge({ immediately: true }); return this; }; Timer.prototype.repeatFor = function (count) { if (count <= 0 || !Number.isFinite(count)) { throw new Error("'count' argument of value '".concat(count, " is not valid'")); } return this.countUp(count + 1); }; Timer.prototype.nowAndRepeatFor = function (count) { if (count <= 0 || !Number.isFinite(count)) { throw new Error("'count' argument of value '".concat(count, " is not valid'")); } return this.countUpNow(count + 1); }; Timer.prototype.until = function (cond) { var _this = this; this.cond = typeof cond === 'boolean' ? !cond : function () { return !cond(_this); }; this.maxCount = 0; this.nudge(); return this; }; Timer.prototype.while = function (cond) { this.maxCount = 0; this.cond = cond; this.nudge(); return this; }; Timer.prototype.nowAndWhile = function (cond) { this.maxCount = 0; this.cond = cond; this.nudge({ immediately: true }); return this; }; Timer.prototype.untilTime = function (ts) { this.while(function () { return Date.now() <= ts; }); return this; }; Timer.prototype.untilTimeNow = function (ts) { this.nowAndWhile(function () { return Date.now() <= ts; }); return this; }; Timer.prototype.forDuration = function (t) { var ms = this.fromUnit(t); if (ms < 0) { throw new Error("Given profile has no time units in [ms,s,m,h,d,w,mo,yr]"); } var startTime = Date.now(); this.while(function () { return Date.now() - startTime <= ms; }); return this; }; Timer.prototype.forDurationNow = function (t) { var ms = this.fromUnit(t); if (ms < 0) { throw new Error("Given profile has no time units in [ms,s,m,h,d,w,mo,yr]"); } var startTime = Date.now(); this.nowAndWhile(function () { return Date.now() - startTime <= ms; }); return this; }; Timer.prototype.untilResult = function (type, options) { var _this = this; if (type === void 0) { type = { backoff: 'default' }; } this.endOnResult = true; this.retryArgsPrep(type, 'untilResult', options); return this.while(function () { return _this.result === null || _this.result === undefined; }); }; Timer.prototype.untilResultNow = function (type, options) { var _this = this; if (type === void 0) { type = { backoff: 'default' }; } this.endOnResult = true; this.retryArgsPrep(type, 'untilResult', options); return this.nowAndWhile(function () { return _this.result === null || _this.result === undefined; }); }; Timer.prototype.backOff = function (type, max, value, start) { if (max === void 0) { max = 1200; } if (value === void 0) { value = 1; } if (start === void 0) { start = this.interval / 1000; } this.retryArgsPrep({ backoff: type }, 'backOff', { backoff: { type: type, max: max, value: value, start: start } }); return this.forever(); }; Timer.prototype.backOffNow = function (type, max, value, start) { if (max === void 0) { max = 1200; } if (value === void 0) { value = 1; } if (start === void 0) { start = this.interval / 1000; } this.retryArgsPrep({ backoff: type }, 'backOff', { backoff: { type: type, max: max, value: value, start: start } }); return this.nowAndForever(); }; Timer.prototype.andOutputTime = function (nameProfile) { var _this = this; this.finishPromise.then(function () { if (!nameProfile) { nameProfile = _this.name; } console['log']("".concat(nameProfile, " took ").concat(_this.deltaFinish, " ms.\n") + " \u2514\u2500 start: ".concat(_this.startTime, ", end: ").concat(_this.endTime, ", finish: ").concat(_this.finishTime, "\n") + (_this.result ? " \u2514\u2500 result: ".concat(_this.result) : "")); }); return this; }; Timer.prototype.andDestroy = function () { this.autoDestroy = true; if (this.endTime > 0) { this.destroy(); } return this; }; Timer.prototype.newBackOffOptions = function (type, max, value, start) { if (max === void 0) { max = 1200; } if (value === void 0) { value = 1; } if (start === void 0) { start = this.interval / 1000; } var profile; if (type === 'expo') { profile = { backoff: { type: type, start: start, value: value, max: max } }; } else if (type === 'linear') { profile = { backoff: { type: type, start: start, value: value, max: max } }; } return profile; }; Timer.prototype.updateInterval = function (newIntervalMs) { this.reg.updateInterval(newIntervalMs); }; Timer.prototype.newBackOffIntervalBehavior = function (options) { var _this = this; return { data: {}, begun: false, callback: function (bh) { var boConf = options.backoff; if (boConf) { if (!bh.begun) { _this.interval = boConf.start * 1000; bh.begun = true; } else { var maxMs = boConf.max * 1000; if (boConf.type === 'expo') { if (_this.interval < maxMs) { _this.interval *= (Math.E * boConf.value); if (_this.interval > maxMs) { _this.interval = maxMs; } _this.updateInterval(_this.interval); } } else if (boConf.type === 'linear') { if (_this.interval < maxMs) { _this.interval += boConf.value * 1000; if (_this.interval > maxMs) { _this.interval = maxMs; } _this.updateInterval(_this.interval); } } } } } }; }; Timer.prototype.startRegCondCheck = function (ms) { if (!this.regWatch) { this.regWatch = new TimerRegistrant({ source: this, ms: ms, repeat: true, immediate: true }); } }; Timer.prototype.getSnapshot = function (context) { var now = Date.now(); var e = { now: now, result: this.result, context: context, maxCount: this.maxCount, count: this.count, nth: this.count + 1, ordinal: this.count + 1, elapsed: now - this.startTime, timer: this, }; return e; }; Timer.prototype.detectStopCond = function () { var shouldStop = (this.cond === false || (this.cond && typeof this.cond !== 'boolean' && !this.cond(this))); if (shouldStop || (this.maxCount !== 0 && this.count === this.maxCount)) { this.end(); } }; Timer.prototype.fromUnit = function (units) { var ms = -1; for (var _i = 0, _a = Object.keys(units); _i < _a.length; _i++) { var unit = _a[_i]; if (unit.length > 2 || unit === 't') { continue; } var n = units[unit]; if (!n || !Number.isFinite(n)) { continue; } if (unit === 'ms') { ms = n; break; } if (unit === 's') { ms = n * 1000; break; } if (unit === 'm') { ms = n * 60000; break; } if (unit === 'h') { ms = n * 3600000; break; } if (unit === 'd') { ms = n * 86400000; break; } if (unit === 'w') { ms = n * 604800000; break; } if (unit === 'mo') { ms = n * 2592000000; break; } if (unit === 'yr') { ms = n * 31536000000; break; } } return ms; }; Timer.prototype.retryArgsPrep = function (type, context, options) { if (type === void 0) { type = { backoff: 'default' }; } if (context === void 0) { context = 'default'; } var bhKey = "".concat(this.ixId, "-").concat(context); if (type.backoff === 'default') { if (this.reg.intervalBehavior[bhKey]) { delete this.reg.intervalBehavior[bhKey]; } } else { var retryOptions = options ? options : this.newBackOffOptions(type.backoff); var bh = this.newBackOffIntervalBehavior(retryOptions); this.reg.intervalBehavior[bhKey] = bh; } }; Timer.prototype.finishingWrapUp = function () { if (this.finished) { return this; } this.finished = true; this.finishTime = Date.now(); this.deltaFinish = this.finishTime - this.startTime; this.deltaEndFinish = this.finishTime - this.endTime; this.ixRx('finish').next(this); for (var _i = 0, _a = this.finishResolves; _i < _a.length; _i++) { var resolve = _a[_i]; try { resolve(this); } catch (error) { var e = this.getSnapshot('finish-error'); e.error = error; this.ixError(error, 1, e); } } if (this.autoDestroy) { this.destroy(); } }; Timer.allActiveTimers = {}; return Timer; }(ix_entity_1.Entity)); exports.Timer = Timer; var TimerRegistrant = (function () { function TimerRegistrant(init) { this.name = ''; this.ms = -1; this.msBefore = -2; this.immediate = false; this.blockInterval = -1; this.repeat = false; this.paused = false; this.skipCount = 0; this.active = true; this.last = 0; this.nowait = false; this.regStart = 0; this.regLast = 0; this.regOverflow = 0; this.intervalBehavior = {}; if (init) { Object.assign(this, init); } if (this.ms < 0) { this.ms = 0; } this.ms = Math.ceil(this.ms); } TimerRegistrant.prototype.invalidate = function () { this.active = false; if (this.regSpot) { var i = 0; for (var _i = 0, _a = this.regSpot; _i < _a.length; _i++) { var regInfo = _a[_i]; if (regInfo.reg === this) { --this.timerblock.pendingCount; this.regSpot.splice(i, 1); break; } ++i; } } this.regSpot = null; }; TimerRegistrant.prototype.update = function (updater) { if (updater) { Object.assign(this, updater); } }; TimerRegistrant.prototype.setImmediate = function () { var _a, _b; (_b = (_a = this.controller) === null || _a === void 0 ? void 0 : _a.baseblock) === null || _b === void 0 ? void 0 : _b.setImmediate(this); return this; }; TimerRegistrant.prototype.registerOn = function (t) { var _a; (_a = this.updatePlacement(t)) === null || _a === void 0 ? void 0 : _a.register(this); return this; }; TimerRegistrant.prototype.updateInterval = function (newMs) { this.ms = Math.ceil(newMs); this.updatePlacement(); }; TimerRegistrant.prototype.updatePlacement = function (t) { if (!t) { t = this.controller; if (!t) { return null; } } if (t !== this.controller) { this.msBefore = -1; this.timerblock = null; } if (this.msBefore === this.ms) { return null; } var matched = null; for (var _i = 0, _a = t.timerblocks; _i < _a.length; _i++) { var timerblock = _a[_i]; if (this.ms <= timerblock.maxSupportedMs) { matched = timerblock; break; } } this.controller = t; this.timerblock = matched; this.msBefore = this.ms; this.blockInterval = this.timerblock.blockMs !== 1 ? Math.ceil(this.ms / this.timerblock.blockMs) : Math.ceil(this.ms); return this.timerblock; }; return TimerRegistrant; }()); exports.TimerRegistrant = TimerRegistrant; function timerInterval(spec, ontick) { return new Timer(spec, ontick).forever(); } exports.timerInterval = timerInterval; //# sourceMappingURL=ix.timer.js.map