@typed/fp
Version:
Data Structures and Resources for fp-ts
131 lines • 4.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.whenIdleEnv = exports.rafEnv = exports.random32Bits = exports.random16Bits = exports.random8Bits = exports.broadcastChannel = exports.HttpEnv = void 0;
const tslib_1 = require("tslib");
/**
* @typed/fp/browser is a place to place implementations of environment from other modules that require or
* are best used with implementations specificall for the browser.
* @since 0.9.4
*/
const Ei = (0, tslib_1.__importStar)(require("fp-ts/Either"));
const D = (0, tslib_1.__importStar)(require("./Disposable"));
const E = (0, tslib_1.__importStar)(require("./Env"));
const R = (0, tslib_1.__importStar)(require("./Resume"));
const S = (0, tslib_1.__importStar)(require("./Stream"));
/**
* @category Environment
* @since 0.9.4
*/
exports.HttpEnv = { http: E.fromResumeK(httpFetchRequest) };
function httpFetchRequest(uri, options = {}) {
return R.async((cb) => {
const { method = 'GET', headers = {}, body } = options;
const disposable = D.settable();
const abortController = new AbortController();
disposable.addDisposable({
dispose: () => abortController.abort(),
});
const init = {
method,
headers: Object.entries(headers).map(([key, value = '']) => [key, value]),
body,
credentials: 'include',
signal: abortController.signal,
};
async function makeRequest() {
const response = await fetch(uri, init);
const headers = {};
response.headers.forEach((value, key) => {
headers[key] = value;
});
const httpResponse = {
status: response.status,
body: await response.json().catch(() => response.text()),
headers,
};
if (!disposable.isDisposed()) {
disposable.addDisposable(cb(Ei.right(httpResponse)));
}
}
makeRequest().catch((error) => {
if (!disposable.isDisposed()) {
disposable.addDisposable(cb(Ei.left(error)));
}
});
return disposable;
});
}
/**
* Constructs an Adapter that utilizes a BroadcastChannel to communicate messages across
* all scripts of the same origin, including workers.
*
* _Note:_ An error will occur, and the stream will fail, if you send events which cannot be
* structurally cloned. See
* https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
* @category Constructor
* @since 0.12.2
*/
const broadcastChannel = (name) => {
const channel = new BroadcastChannel(name);
const send = (event) => channel.postMessage(event);
const stream = S.newStream((sink, scheduler) => {
const onMessage = (event) => sink.event(scheduler.currentTime(), event.data);
const onMessageError = (event) => sink.error(scheduler.currentTime(), event.data);
channel.addEventListener('message', onMessage);
channel.addEventListener('messageerror', onMessageError);
return {
dispose: () => {
channel.removeEventListener('message', onMessage);
channel.removeEventListener('messageerror', onMessageError);
},
};
});
return [send, stream];
};
exports.broadcastChannel = broadcastChannel;
/**
* Utilize the Crypto API to generate 8-bit numbers
* @category Constructor
* @since 0.12.2
*/
const random8Bits = (count) => E.fromIO(() => [...crypto.getRandomValues(new Uint8Array(count))]);
exports.random8Bits = random8Bits;
/**
* Utilize the Crypto API to generate 16-bit numbers
* @category Constructor
* @since 0.12.2
*/
const random16Bits = (count) => E.fromIO(() => [...crypto.getRandomValues(new Uint16Array(count))]);
exports.random16Bits = random16Bits;
/**
* Utilize the Crypto API to generate 32-bit numbers
* @category Constructor
* @since 0.12.2
*/
const random32Bits = (count) => E.fromIO(() => [...crypto.getRandomValues(new Uint32Array(count))]);
exports.random32Bits = random32Bits;
/**
* @category Environment
* @since 0.13.2
*/
exports.rafEnv = {
raf: R.async((resume) => {
const disposable = D.settable();
let handle = requestAnimationFrame(() => (handle = requestAnimationFrame((n) => disposable.addDisposable(resume(n)))));
disposable.addDisposable({ dispose: () => cancelAnimationFrame(handle) });
return disposable;
}),
};
/**
* @category Environment
* @since 0.13.2
*/
exports.whenIdleEnv = {
whenIdle: R.async((cb) => {
const disposable = D.settable();
const handle = window.requestIdleCallback((d) => disposable.addDisposable(cb(d)));
disposable.addDisposable({ dispose: () => cancelAnimationFrame(handle) });
return disposable;
}),
};
//# sourceMappingURL=browser.js.map