UNPKG

@typed/fp

Version:

Data Structures and Resources for fp-ts

358 lines 10.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createHistoryEnv = exports.parseHref = exports.writeFile = exports.write = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.readdir = exports.readFile = exports.read = exports.mkdir = exports.link = exports.copyFile = exports.chmod = exports.HttpEnv = void 0; const tslib_1 = require("tslib"); /** * @typed/fp/node is a place to place implementations of environment from other modules that require or * are best used with implementations specifically for node.js. * @since 0.9.4 */ const Ei = (0, tslib_1.__importStar)(require("fp-ts/Either")); const fs = (0, tslib_1.__importStar)(require("fs")); const node_fetch_1 = (0, tslib_1.__importDefault)(require("node-fetch")); const D = (0, tslib_1.__importStar)(require("./Disposable")); const E = (0, tslib_1.__importStar)(require("./Env")); const EnvEither_1 = require("./EnvEither"); const R = (0, tslib_1.__importStar)(require("./Resume")); /** * @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: body !== null && body !== void 0 ? body : undefined, credentials: 'include', signal: abortController.signal, }; async function makeRequest() { const response = await (0, node_fetch_1.default)(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; }); } /** * @category FS * @since 0.13.1 */ exports.chmod = (0, EnvEither_1.fromPromiseK)(fs.promises.chmod); /** * @category FS * @since 0.13.1 */ exports.copyFile = (0, EnvEither_1.fromPromiseK)(fs.promises.copyFile); /** * @category FS * @since 0.13.1 */ exports.link = (0, EnvEither_1.fromPromiseK)(fs.promises.link); /** * @category FS * @since 0.13.1 */ exports.mkdir = (0, EnvEither_1.fromPromiseK)(fs.promises.mkdir); /** * @category FS * @since 0.13.1 */ exports.read = (0, EnvEither_1.fromPromiseK)(fs.promises.read); /** * @category FS * @since 0.13.1 */ exports.readFile = (0, EnvEither_1.fromPromiseK)(fs.promises.readFile); /** * @category FS * @since 0.13.1 */ exports.readdir = (0, EnvEither_1.fromPromiseK)(fs.promises.readdir); /** * @category FS * @since 0.13.1 */ exports.rm = (0, EnvEither_1.fromPromiseK)(fs.promises.rm); /** * @category FS * @since 0.13.1 */ exports.rmdir = (0, EnvEither_1.fromPromiseK)(fs.promises.rmdir); /** * @category FS * @since 0.13.1 */ exports.stat = (0, EnvEither_1.fromPromiseK)(fs.promises.stat); /** * @category FS * @since 0.13.1 */ exports.symlink = (0, EnvEither_1.fromPromiseK)(fs.promises.symlink); /** * @category FS * @since 0.13.1 */ exports.unlink = (0, EnvEither_1.fromPromiseK)(fs.promises.unlink); /** * @category FS * @since 0.13.1 */ exports.write = (0, EnvEither_1.fromPromiseK)(fs.promises.write); /** * @category FS * @since 0.13.1 */ exports.writeFile = (0, EnvEither_1.fromPromiseK)(fs.promises.writeFile); /** * An in-memory implementation of `History`. * @category In-Memory Mock * @since 0.13.2 * @internal */ class ServerHistory { constructor(location) { // Does not affect behavior this.scrollRestoration = 'auto'; // tslint:disable-next-line:variable-name this._index = 0; this.location = location; this._states = [{ state: null, url: this.location.pathname }]; } set index(value) { this._index = value; const { url } = this._states[this._index]; this.location.replace(url); } get index() { return this._index; } get length() { return this._states.length; } get state() { const { state } = this._states[this.index]; return state; } go(quanity = 0) { if (quanity === 0) { return void 0; } const minIndex = 0; const maxIndex = this.length - 1; this.index = Math.max(minIndex, Math.min(maxIndex, this.index + quanity)); } back() { this.go(-1); } forward() { this.go(1); } pushState(state, _, url) { this._states = this._states.slice(0, this.index).concat({ state, url }); this.index = this._states.length - 1; } replaceState(state, _, url) { this._states[this.index] = { state, url }; } } const HTTPS_PROTOCOL = 'https:'; const HTTPS_DEFAULT_PORT = '443'; const HTTP_DEFAULT_PORT = '80'; /** * An in-memory implementation of `Location`. * @category In-Memory Mock * @since 0.13.2 * @internal */ class ServerLocation { constructor(url) { this.updateHref(url); } get ancestorOrigins() { return []; } get hash() { return parseValue('hash', this); } set hash(value) { const hash = value.startsWith('#') ? value : '#' + value; replace('hash', hash, this); } get host() { return parseValue('host', this); } set host(value) { replace('host', value, this); } get hostname() { return parseValue('hostname', this); } set hostname(value) { replace('hostname', value, this); } get pathname() { return parseValue('pathname', this); } set pathname(value) { replace('pathname', value, this); } get port() { const { href } = this; const { port, protocol } = parseHref(href); if (port) { return port; } return protocol === HTTPS_PROTOCOL ? HTTPS_DEFAULT_PORT : HTTP_DEFAULT_PORT; } set port(value) { replace('port', value, this); } get protocol() { return parseValue('protocol', this) || 'http:'; } set protocol(value) { replace('protocol', value, this); } get search() { return parseValue('search', this); } set search(value) { const search = value.startsWith('?') ? value : '?' + value; replace('search', search, this); } get origin() { return this.protocol + '//' + this.host; } assign(url) { this.updateHref(url); if (this.history) { this.history.pushState(null, '', this.href); } } reload() { // Does not have defined behavior outside of browser } replace(url) { this.updateHref(url); if (this.history) { this.history.replaceState(null, '', this.href); } } toString() { return this.href; } // ServerLocation Specific setHistory(history) { this.history = history; return this; } updateHref(url) { const parsed = parseHref(url); const { host, relative } = parsed; let href = parsed.href; if (this.host && !host) { href = this.host + href; } const { protocol } = parseHref(href); if (href !== relative && this.protocol && !protocol) { href = this.protocol + '//' + href; } this.href = href; } } function replace(key, value, location) { const { href } = location; const currentValue = parseHref(href)[key]; const updateHref = href.replace(currentValue, value); location.replace(updateHref); if (location.history) { location.history.pushState(null, '', location.href); } } function parseValue(key, location) { return parseHref(location.href)[key]; } const HREF_REGEX = /^(?:([^:/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:/?#]*)(?::(\d*))?))?((((?:[^?#/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/; /** * Parses an href into JSON. * @category Parser * @since 0.13.2 * */ function parseHref(href) { const matches = HREF_REGEX.exec(href); const parsedHref = {}; for (let i = 0; i < keyCount; ++i) { const key = keys[i]; let value = matches[i] || ''; if (key === 'search' && value) { value = '?' + value; } if (key === 'protocol' && value && !value.endsWith(':')) { value = value + ':'; } if (key === 'hash') { value = '#' + value; } parsedHref[key] = value; } return parsedHref; } exports.parseHref = parseHref; const keys = [ 'href', 'protocol', 'host', 'userInfo', 'username', 'password', 'hostname', 'port', 'relative', 'pathname', 'directory', 'file', 'search', 'hash', ]; const keyCount = keys.length; /** * Create A History Environment that works in browser and non-browser environments * @param href :: initial href to use * @category Environment * @since 0.13.2 */ function createHistoryEnv(href = '/') { const serverLocation = new ServerLocation(href); const serverHistory = new ServerHistory(serverLocation); serverLocation.setHistory(serverHistory); return { location: serverLocation, history: serverHistory, }; } exports.createHistoryEnv = createHistoryEnv; //# sourceMappingURL=node.js.map