svelte-statusable
Version:
Super tiny, simple to use SvelteJS store to control your application status.
317 lines (255 loc) • 8.16 kB
JavaScript
var statusable = (function (exports) {
'use strict';
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) {
symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
}
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function noop() {}
function safe_not_equal(a, b) {
return a != a ? b == b : a !== b || a && typeof a === 'object' || typeof a === 'function';
}
Promise.resolve();
const subscriber_queue = [];
/**
* Creates a `Readable` store that allows reading by subscription.
* @param value initial value
* @param {StartStopNotifier}start start and stop notifications for subscriptions
*/
function readable(value, start) {
return {
subscribe: writable(value, start).subscribe
};
}
/**
* Create a `Writable` store that allows both updating and reading by subscription.
* @param {*=}value initial value
* @param {StartStopNotifier=}start start and stop notifications for subscriptions
*/
function writable(value, start = noop) {
let stop;
const subscribers = new Set();
function set(new_value) {
if (safe_not_equal(value, new_value)) {
value = new_value;
if (stop) {
// store is ready
const run_queue = !subscriber_queue.length;
for (const subscriber of subscribers) {
subscriber[1]();
subscriber_queue.push(subscriber, value);
}
if (run_queue) {
for (let i = 0; i < subscriber_queue.length; i += 2) {
subscriber_queue[i][0](subscriber_queue[i + 1]);
}
subscriber_queue.length = 0;
}
}
}
}
function update(fn) {
set(fn(value));
}
function subscribe(run, invalidate = noop) {
const subscriber = [run, invalidate];
subscribers.add(subscriber);
if (subscribers.size === 1) {
stop = start(set) || noop;
}
run(value);
return () => {
subscribers.delete(subscriber);
if (subscribers.size === 0) {
stop();
stop = null;
}
};
}
return {
set,
update,
subscribe
};
}
var _excluded = ["url", "abort", "payload", "retry"];
var hasWindow = typeof window !== 'undefined';
var hasNavigator = typeof navigator !== 'undefined';
var hasDocument = typeof document !== 'undefined';
var hasEventSource = typeof EventSource !== 'undefined';
var hasAbortController = typeof AbortController !== 'undefined';
var defaultRetry = 10000;
function setIntervalImmediately(func, interval) {
func();
return setInterval(func, interval);
}
function heartbeat(_ref) {
var url = _ref.url,
_ref$abort = _ref.abort,
abort = _ref$abort === void 0 ? 0 : _ref$abort,
_ref$payload = _ref.payload,
payload = _ref$payload === void 0 ? false : _ref$payload;
_ref.retry;
var options = _objectWithoutProperties(_ref, _excluded);
/*eslint no-unused-vars: "off"*/
if (abort && hasAbortController) {
var ac = new AbortController();
options.signal = ac.signal;
setTimeout(function () {
return ac.abort();
}, abort);
}
return fetch(url, options).then(function (res) {
return payload ? res.json() : res.type === 'opaque' || res.ok;
}).catch(function () {
return false;
});
}
function statusable(_ref2) {
var ping = _ref2.ping,
sse = _ref2.sse;
var value = {
online: hasNavigator ? navigator.onLine : true,
hidden: hasDocument ? document.hidden : false,
heartbeat: !hasWindow,
// for SSR
stream: !hasWindow
};
if (typeof ping === 'string') {
ping = {
url: ping,
method: 'HEAD',
cache: 'no-cache',
credentials: 'omit',
referrerPolicy: 'no-referrer'
};
}
if (typeof sse === 'string') {
sse = {
url: sse,
withCredentials: false
};
}
return readable(value, function (set) {
if (!hasWindow || !hasNavigator || !hasDocument) return;
var es;
var interval;
function assign(key, val) {
if (value[key] === val) return;
set(value = _objectSpread2(_objectSpread2({}, value), {}, _defineProperty({}, key, val)));
}
function online() {
assign('online', navigator.onLine);
}
function visibility() {
assign('hidden', document.hidden);
}
function stream(e) {
assign('stream', e.target.readyState === EventSource.OPEN);
}
if (sse && hasEventSource) {
es = new EventSource(sse.url, {
withCredentials: sse.withCredentials
});
es.addEventListener('open', stream);
es.addEventListener('error', stream);
if (sse.event) {
es.addEventListener(sse.event, stream);
}
assign('stream', es.readyState === EventSource.OPEN);
}
if (ping) {
interval = setIntervalImmediately(function () {
if (document.hidden || !navigator.onLine) return;
heartbeat(ping).then(function (heartbeat) {
return assign('heartbeat', heartbeat);
});
}, ping.retry || defaultRetry);
}
window.addEventListener('online', online);
window.addEventListener('offline', online);
window.addEventListener('visibilitychange', visibility);
return function () {
window.removeEventListener('online', online);
window.removeEventListener('offline', online);
window.removeEventListener('visibilitychange', visibility);
if (es) {
es.removeEventListener('open', stream);
es.removeEventListener('error', stream);
if (sse.event) {
es.removeEventListener(sse.event, stream);
}
}
clearInterval(interval);
};
});
}
exports.statusable = statusable;
Object.defineProperty(exports, '__esModule', { value: true });
return exports;
})({});