├── .gitignore ├── .travis.yml ├── .prettierrc ├── src ├── helpers │ ├── other.ts │ └── maybe.ts ├── tests.ts └── index.ts ├── tsconfig.es6.json ├── .prettierignore ├── tsconfig.json ├── .vscode └── settings.json ├── .editorconfig ├── package.json ├── README.md └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 10.13.0 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } 5 | -------------------------------------------------------------------------------- /src/helpers/other.ts: -------------------------------------------------------------------------------- 1 | export const isNonEmptyString = (str: string) => str.length > 0; 2 | -------------------------------------------------------------------------------- /tsconfig.es6.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist/es6", 5 | "module": "ES6" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # https://prettier.io/docs/en/ignore.html 2 | 3 | /chrome/ 4 | # CLI ignores Node modules by default https://github.com/prettier/prettier/pull/1683, VSCode 5 | # extension does not https://github.com/prettier/prettier-vscode/issues/198, 6 | # https://github.com/prettier/prettier-vscode/issues/548. 7 | /dist/ 8 | 9 | node_modules/ 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS", 4 | "moduleResolution": "Node", 5 | "target": "ES5", 6 | "strict": true, 7 | "noUncheckedIndexedAccess": true, 8 | "noImplicitReturns": true, 9 | "sourceMap": true, 10 | "outDir": "./dist/lib", 11 | "rootDir": "./src/", 12 | "declaration": true 13 | }, 14 | "files": ["./src/index.ts", "./src/tests.ts"] 15 | } 16 | -------------------------------------------------------------------------------- /src/helpers/maybe.ts: -------------------------------------------------------------------------------- 1 | // https://github.com/OliverJAsh/simple-maybe 2 | 3 | type Maybe = null | T; 4 | 5 | export const isDefined = (maybeT: Maybe): maybeT is T => maybeT !== null; 6 | 7 | // extend {} to ensure we're mapping to a non-null type 8 | export const mapMaybe = (f: (t: T) => B) => (maybeT: Maybe): Maybe => 9 | isDefined(maybeT) ? f(maybeT) : maybeT; 10 | export const getOrElseMaybe = (fallback: () => T) => (maybeT: Maybe): T => 11 | isDefined(maybeT) ? maybeT : fallback(); 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.rulers": [ 3 | 100 // Enforced by Prettier 4 | ], 5 | 6 | // We use the language service plugin for this 7 | "tslint.enable": false, 8 | 9 | "editor.codeActionsOnSave": { 10 | "source.organizeImports": true 11 | }, 12 | 13 | "[typescript]": { 14 | "editor.formatOnSave": true 15 | }, 16 | "[javascript]": { 17 | "editor.formatOnSave": true 18 | }, 19 | "[json]": { 20 | "editor.formatOnSave": true 21 | }, 22 | "[jsonc]": { 23 | "editor.formatOnSave": true 24 | }, 25 | "[markdown]": { 26 | "editor.formatOnSave": true 27 | }, 28 | 29 | "typescript.tsdk": "node_modules/typescript/lib" 30 | } 31 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Note: prettier inherits from `indent_style`, `indent_size`/`tab_width`, and `max_line_length` 2 | # https://github.com/prettier/prettier/blob/cecf0657a521fa265b713274ed67ca39be4142cf/docs/api.md#prettierresolveconfigfilepath--options 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.{js,ts}] 11 | # https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#max_line_length 12 | max_line_length = 100 13 | 14 | [package.json] 15 | indent_size = 2 16 | 17 | # Git is sensitive to whitespace in diff files 18 | # https://stackoverflow.com/questions/50258565/git-editing-hunks-fails-when-file-has-other-hunks/50275053#50275053 19 | [*.diff] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "url-transformers", 3 | "main": "./dist/lib/index.js", 4 | "module": "./dist/es6/index.js", 5 | "typings": "./dist/lib/index.d.ts", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/unsplash/url-transformers.git" 9 | }, 10 | "version": "0.0.10", 11 | "scripts": { 12 | "compile": "rm -rf ./dist/ && tsc -p ./tsconfig.json && tsc -p ./tsconfig.es6.json && import-path-rewrite", 13 | "test": "npm run compile && node --require source-map-support/register ./dist/lib/tests.js", 14 | "format": "prettier --write './**/*.{ts,js,json,md}' '.prettierrc'", 15 | "prepublishOnly": "npm run compile" 16 | }, 17 | "files": [ 18 | "dist" 19 | ], 20 | "dependencies": { 21 | "@types/node": "^14.14.16", 22 | "fp-ts": "^2.9.2", 23 | "monocle-ts": "^2.3.3" 24 | }, 25 | "devDependencies": { 26 | "import-path-rewrite": "github:gcanti/import-path-rewrite", 27 | "prettier": "^2.2.1", 28 | "source-map-support": "^0.5.19", 29 | "typescript": "^4.1.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ Archived ⚠️ 2 | 3 | This library is no longer maintained. 4 | 5 | We've migrated to alternatives based atop the native `URL` and `URLSearchParams` APIs. 6 | 7 | --- 8 | 9 | # `url-transformers` 10 | 11 | A small helper library for manipulating URL strings in Node and in the browser. `url-transformers` provides several functions for common URL transformations, such as adding a search/query string to a URL or appending to the URL pathname. 12 | 13 | Currently `url-transformers` provides the following helpers: 14 | 15 | - `mapUrl` 16 | - `replaceQueryInUrl` 17 | - `addQueryToUrl` 18 | - `replacePathInUrl` 19 | - `replacePathnameInUrl` 20 | - `appendPathnameToUrl` 21 | - `replaceHashInUrl` 22 | 23 | There are many more possibilities, so we would love for you to help us grow this collection! 24 | 25 | Currently we don't have documentation, however the code is strongly typed using TypeScript, and it should be easy to scan the function signatures. See the [tests] for example usage. 26 | 27 | ## Installation 28 | 29 | ```sh 30 | yarn add url-transformers 31 | npm install url-transformers 32 | ``` 33 | 34 | ## Dependencies 35 | 36 | This project depends on [`monocle-ts`](https://github.com/gcanti/monocle-ts) (lenses library) and [`fp-ts`](https://github.com/gcanti/fp-ts). If tree shaking is used (via the `module` field in `package.json`) these dependencies will have a negligible impact on the bundle size—at the time of writing they only contribute ~500 bytes (gzipped) to the bundle. 37 | 38 | ## Development 39 | 40 | ```sh 41 | yarn 42 | 43 | npm run test 44 | 45 | npm run prepublishOnly && npm version patch && npm publish && git push && git push --tags 46 | ``` 47 | 48 | [tests]: ./src/tests.ts 49 | -------------------------------------------------------------------------------- /src/tests.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { flow, pipe } from 'fp-ts/lib/function'; 3 | import * as urlHelpers from 'url'; 4 | import { 5 | addQueryToUrl, 6 | appendPathnameToUrl, 7 | mapParsedUrl, 8 | mapUrl, 9 | replaceHashInUrl, 10 | replacePathInParsedUrl, 11 | replacePathInUrl, 12 | replacePathnameInParsedUrl, 13 | replacePathnameInUrl, 14 | replaceQueryInParsedUrl, 15 | replaceQueryInUrl, 16 | } from './index'; 17 | 18 | assert.deepEqual( 19 | pipe( 20 | urlHelpers.parse('https://foo.com/bar', true), 21 | mapParsedUrl((parsedUrl) => ({ 22 | ...parsedUrl, 23 | pathname: '/foo', 24 | query: { a: 'b' }, 25 | })), 26 | urlHelpers.format, 27 | ), 28 | 'https://foo.com/foo?a=b', 29 | ); 30 | 31 | assert.deepEqual( 32 | pipe( 33 | 'https://foo.com/bar', 34 | mapUrl((parsedUrl) => ({ 35 | ...parsedUrl, 36 | pathname: '/foo', 37 | query: { a: 'b', foo: 1 }, 38 | })), 39 | ), 40 | 'https://foo.com/foo?a=b&foo=1', 41 | ); 42 | 43 | assert.deepEqual( 44 | pipe( 45 | 'https://foo.com/bar', 46 | mapUrl( 47 | flow( 48 | replacePathnameInParsedUrl(() => '/foo'), 49 | replaceQueryInParsedUrl(() => ({ a: 'b' })), 50 | ), 51 | ), 52 | ), 53 | 'https://foo.com/foo?a=b', 54 | ); 55 | 56 | assert.strictEqual( 57 | replaceQueryInUrl({ foo: 1 })( 58 | '/foo?string=string&number=1&boolean=true&strings=string1&strings=string2', 59 | ), 60 | '/foo?foo=1', 61 | ); 62 | 63 | assert.strictEqual( 64 | replaceQueryInUrl({ foo: 1 })( 65 | 'http://foo.com/?string=string&number=1&boolean=true&strings=string1&strings=string2', 66 | ), 67 | 'http://foo.com/?foo=1', 68 | ); 69 | assert.strictEqual( 70 | replaceQueryInUrl({})( 71 | 'http://foo.com/?string=string&number=1&boolean=true&strings=string1&strings=string2', 72 | ), 73 | 'http://foo.com/', 74 | ); 75 | 76 | assert.strictEqual( 77 | addQueryToUrl({ 78 | string: 'string', 79 | number: 1, 80 | boolean: true, 81 | strings: ['string1', 'string2'], 82 | })('http://foo.com/'), 83 | 'http://foo.com/?string=string&number=1&boolean=true&strings=string1&strings=string2', 84 | ); 85 | assert.strictEqual( 86 | addQueryToUrl({ a: 'b' })('http://foo:bar@baz.com/'), 87 | 'http://foo:bar@baz.com/?a=b', 88 | ); 89 | assert.strictEqual( 90 | addQueryToUrl({ c: 'd' })('http://foo.com/?a=b&b=c'), 91 | 'http://foo.com/?a=b&b=c&c=d', 92 | ); 93 | 94 | assert.strictEqual( 95 | pipe( 96 | 'https://foo.com/foo?example', 97 | mapUrl( 98 | replacePathInParsedUrl((prev) => ({ pathname: `${prev.pathname}/bar`, query: null })), 99 | ), 100 | ), 101 | 'https://foo.com/foo/bar', 102 | ); 103 | assert.strictEqual( 104 | pipe( 105 | 'https://foo.com/foo?example', 106 | mapUrl( 107 | replacePathInParsedUrl((prev) => ({ 108 | pathname: `${prev.pathname}/bar`, 109 | query: prev.query, 110 | })), 111 | ), 112 | ), 113 | 'https://foo.com/foo/bar?example=', 114 | ); 115 | assert.strictEqual( 116 | pipe( 117 | 'https://foo.com/foo?example', 118 | mapUrl(replacePathInParsedUrl({ pathname: null, query: null })), 119 | ), 120 | 'https://foo.com', 121 | ); 122 | 123 | assert.strictEqual( 124 | replacePathInUrl((prev) => `${prev}/bar`)('https://foo.com/foo'), 125 | 'https://foo.com/foo/bar', 126 | ); 127 | assert.strictEqual( 128 | replacePathInUrl((prev) => `${prev}/bar`)('https://foo.com/foo?example'), 129 | 'https://foo.com/foo?example=%2Fbar', 130 | ); 131 | assert.strictEqual(replacePathInUrl('/bar')('https://foo.com/foo?example'), 'https://foo.com/bar'); 132 | assert.strictEqual(replacePathInUrl(null)('https://foo.com/foo?example'), 'https://foo.com'); 133 | 134 | assert.strictEqual(replacePathnameInUrl('/bar')('https://foo.com/foo'), 'https://foo.com/bar'); 135 | assert.strictEqual(replacePathnameInUrl(null)('https://foo.com/foo'), 'https://foo.com'); 136 | assert.strictEqual( 137 | replacePathnameInUrl('/bar')('https://foo.com/foo?example='), 138 | 'https://foo.com/bar?example=', 139 | ); 140 | 141 | assert.strictEqual(appendPathnameToUrl('/bar')('/foo'), '/foo/bar'); 142 | assert.strictEqual(appendPathnameToUrl('/bar')('/foo/'), '/foo/bar'); 143 | assert.strictEqual(appendPathnameToUrl('/bar')('/foo?example='), '/foo/bar?example='); 144 | assert.strictEqual(appendPathnameToUrl('/bar')('/@foo'), '/@foo/bar'); 145 | 146 | assert.strictEqual(replaceHashInUrl('#bar')('/foo'), '/foo#bar'); 147 | assert.strictEqual(replaceHashInUrl(null)('/foo#bar'), '/foo'); 148 | assert.strictEqual(replaceHashInUrl('#baz')('/foo#bar'), '/foo#baz'); 149 | assert.strictEqual(replaceHashInUrl((prev) => `${prev}2`)('/foo#bar'), '/foo#bar2'); 150 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { flow, pipe } from 'fp-ts/lib/function'; 2 | import * as L from 'monocle-ts/lib/Lens'; 3 | import { ParsedUrlQueryInput } from 'querystring'; 4 | import * as urlHelpers from 'url'; 5 | import { getOrElseMaybe, mapMaybe } from './helpers/maybe'; 6 | import { isNonEmptyString } from './helpers/other'; 7 | 8 | interface NodeUrlObjectWithParsedQuery extends urlHelpers.UrlObject { 9 | query?: ParsedUrlQueryInput | null; 10 | } 11 | 12 | type UpdateFn = (prev: T) => T; 13 | type Update = T | UpdateFn; 14 | 15 | const getPathnameFromParts = (parts: string[]) => `/${parts.join('/')}`; 16 | 17 | const getPartsFromPathname = (pathname: string) => pathname.split('/').filter(isNonEmptyString); 18 | 19 | const parseUrlWithQueryString = (url: string) => 20 | urlHelpers.parse( 21 | url, 22 | // Parse the query string 23 | true, 24 | ); 25 | 26 | // We omit some properties since they're just serialized versions of other properties. 27 | interface ParsedUrl 28 | extends Required< 29 | Pick< 30 | NodeUrlObjectWithParsedQuery, 31 | 'auth' | 'hash' | 'hostname' | 'pathname' | 'port' | 'protocol' | 'query' | 'slashes' 32 | > 33 | > {} 34 | 35 | export const urlLens = L.id(); 36 | 37 | const lensModifyOrSet = (sa: L.Lens) => (f: A | ((a: A) => A)) => 38 | f instanceof Function ? pipe(sa, L.modify(f)) : sa.set(f); 39 | 40 | const convertNodeUrl = ({ 41 | auth, 42 | hash, 43 | hostname, 44 | pathname, 45 | port, 46 | protocol, 47 | query, 48 | slashes, 49 | }: urlHelpers.UrlWithParsedQuery): ParsedUrl => ({ 50 | auth, 51 | hash, 52 | hostname, 53 | pathname, 54 | port, 55 | protocol, 56 | query, 57 | slashes, 58 | }); 59 | 60 | const parseUrl = flow(parseUrlWithQueryString, convertNodeUrl); 61 | const formatUrl = (parsedUrl: ParsedUrl) => urlHelpers.format(parsedUrl); 62 | 63 | type Codec = { 64 | decode: (io: IO) => A; 65 | encode: (a: A) => IO; 66 | }; 67 | 68 | const urlCodec: Codec = { 69 | decode: parseUrl, 70 | encode: formatUrl, 71 | }; 72 | 73 | type MapParsedUrlFn = (parsedUrl: ParsedUrl) => ParsedUrl; 74 | export const mapParsedUrl = (fn: MapParsedUrlFn): MapParsedUrlFn => fn; 75 | 76 | type MapUrlFn = (url: string) => string; 77 | export const mapUrl = (fn: MapParsedUrlFn): MapUrlFn => flow(urlCodec.decode, fn, urlCodec.encode); 78 | 79 | export const queryLens: L.Lens = pipe(urlLens, L.prop('query')); 80 | 81 | export const replaceQueryInParsedUrl = pipe(queryLens, lensModifyOrSet); 82 | 83 | export const replaceQueryInUrl = flow(replaceQueryInParsedUrl, mapUrl); 84 | 85 | export const addQueryToParsedUrl = (queryToAppend: ParsedUrl['query']): MapParsedUrlFn => 86 | replaceQueryInParsedUrl((prevQuery) => ({ ...prevQuery, ...queryToAppend })); 87 | 88 | export const addQueryToUrl = flow(addQueryToParsedUrl, mapUrl); 89 | 90 | interface ParsedPath extends Pick {} 91 | 92 | export const pathLens: L.Lens = pipe(urlLens, L.props('pathname', 'query')); 93 | 94 | const parsePath = flow(parseUrlWithQueryString, pathLens.get); 95 | 96 | const parseNullablePath = flow( 97 | mapMaybe(parsePath), 98 | getOrElseMaybe((): ParsedPath => ({ query: null, pathname: null })), 99 | ); 100 | 101 | const formatPath = (parsedPath: ParsedPath) => urlHelpers.format(parsedPath); 102 | 103 | type Path = urlHelpers.Url['path']; 104 | 105 | const pathCodec: Codec = { 106 | decode: parseNullablePath, 107 | encode: formatPath, 108 | }; 109 | 110 | const convertUpdatePathFnToUpdateParsedPathFn = ( 111 | updatePath: UpdateFn, 112 | ): UpdateFn => flow(pathCodec.encode, updatePath, pathCodec.decode); 113 | 114 | const convertUpdatePathToUpdateParsedPath = (newPath: Update): Update => 115 | typeof newPath === 'function' 116 | ? convertUpdatePathFnToUpdateParsedPathFn(newPath) 117 | : parseNullablePath(newPath); 118 | 119 | export const replacePathInParsedUrl = pipe(pathLens, lensModifyOrSet); 120 | 121 | export const replacePathInUrl = flow( 122 | convertUpdatePathToUpdateParsedPath, 123 | replacePathInParsedUrl, 124 | mapUrl, 125 | ); 126 | 127 | export const pathnameLens: L.Lens = pipe( 128 | urlLens, 129 | L.prop('pathname'), 130 | ); 131 | 132 | export const replacePathnameInParsedUrl = pipe(pathnameLens, lensModifyOrSet); 133 | 134 | export const replacePathnameInUrl = flow(replacePathnameInParsedUrl, mapUrl); 135 | 136 | export const appendPathnameToParsedUrl = (pathnameToAppend: string): MapParsedUrlFn => 137 | replacePathnameInParsedUrl((prevPathname) => { 138 | const pathnameParts = pipe( 139 | prevPathname, 140 | mapMaybe(getPartsFromPathname), 141 | getOrElseMaybe((): string[] => []), 142 | ); 143 | const pathnamePartsToAppend = getPartsFromPathname(pathnameToAppend); 144 | const newPathnameParts = [...pathnameParts, ...pathnamePartsToAppend]; 145 | const newPathname = getPathnameFromParts(newPathnameParts); 146 | return newPathname; 147 | }); 148 | 149 | export const appendPathnameToUrl = flow(appendPathnameToParsedUrl, mapUrl); 150 | 151 | export const hashLens: L.Lens = pipe(urlLens, L.prop('hash')); 152 | 153 | export const replaceHashInParsedUrl = pipe(hashLens, lensModifyOrSet); 154 | 155 | export const replaceHashInUrl = flow(replaceHashInParsedUrl, mapUrl); 156 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/node@^14.14.16": 6 | version "14.14.16" 7 | resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.16.tgz#3cc351f8d48101deadfed4c9e4f116048d437b4b" 8 | integrity sha512-naXYePhweTi+BMv11TgioE2/FXU4fSl29HAH1ffxVciNsH3rYXjNP2yM8wqmSm7jS20gM8TIklKiTen+1iVncw== 9 | 10 | ansi-styles@^4.1.0: 11 | version "4.3.0" 12 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 13 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 14 | dependencies: 15 | color-convert "^2.0.1" 16 | 17 | balanced-match@^1.0.0: 18 | version "1.0.0" 19 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 20 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 21 | 22 | brace-expansion@^1.1.7: 23 | version "1.1.11" 24 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 25 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 26 | dependencies: 27 | balanced-match "^1.0.0" 28 | concat-map "0.0.1" 29 | 30 | buffer-from@^1.0.0: 31 | version "1.1.1" 32 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 33 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 34 | 35 | chalk@^3.0.0: 36 | version "3.0.0" 37 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" 38 | integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== 39 | dependencies: 40 | ansi-styles "^4.1.0" 41 | supports-color "^7.1.0" 42 | 43 | color-convert@^2.0.1: 44 | version "2.0.1" 45 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 46 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 47 | dependencies: 48 | color-name "~1.1.4" 49 | 50 | color-name@~1.1.4: 51 | version "1.1.4" 52 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 53 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 54 | 55 | concat-map@0.0.1: 56 | version "0.0.1" 57 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 58 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 59 | 60 | fp-ts@^2.9.2: 61 | version "2.9.2" 62 | resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.9.2.tgz#0f51b6bdb52fe4314e96c93bb5f15a2969c562d9" 63 | integrity sha512-fswVB9E5Aq9+jCZU+4heaJTYuv8m5/vn9ii12pmxduyf3YwP4AQKFmFO66YDNzL+c0iP6G8Cav5gpvc+2emOAw== 64 | 65 | fs.realpath@^1.0.0: 66 | version "1.0.0" 67 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 68 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 69 | 70 | glob@^7.1.6: 71 | version "7.1.6" 72 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 73 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 74 | dependencies: 75 | fs.realpath "^1.0.0" 76 | inflight "^1.0.4" 77 | inherits "2" 78 | minimatch "^3.0.4" 79 | once "^1.3.0" 80 | path-is-absolute "^1.0.0" 81 | 82 | has-flag@^4.0.0: 83 | version "4.0.0" 84 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 85 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 86 | 87 | "import-path-rewrite@github:gcanti/import-path-rewrite": 88 | version "0.0.1" 89 | resolved "https://codeload.github.com/gcanti/import-path-rewrite/tar.gz/39b4178f9ff80aed3fa18a702584e0d0f0d6d8bc" 90 | dependencies: 91 | chalk "^3.0.0" 92 | glob "^7.1.6" 93 | 94 | inflight@^1.0.4: 95 | version "1.0.6" 96 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 97 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 98 | dependencies: 99 | once "^1.3.0" 100 | wrappy "1" 101 | 102 | inherits@2: 103 | version "2.0.4" 104 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 105 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 106 | 107 | minimatch@^3.0.4: 108 | version "3.0.4" 109 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 110 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 111 | dependencies: 112 | brace-expansion "^1.1.7" 113 | 114 | monocle-ts@^2.3.3: 115 | version "2.3.3" 116 | resolved "https://registry.yarnpkg.com/monocle-ts/-/monocle-ts-2.3.3.tgz#1e6d83dcf42bcb96b74fdda07813c2a47ec6cfa4" 117 | integrity sha512-pcQyauWO2vapxyZgbhTd73Dv8TmTELx1rL81bvrtPO2sUYTi1MIHmw3j/iMyeNaJwTmnGNAjqJpYV8Gq1Eu68g== 118 | 119 | once@^1.3.0: 120 | version "1.4.0" 121 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 122 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 123 | dependencies: 124 | wrappy "1" 125 | 126 | path-is-absolute@^1.0.0: 127 | version "1.0.1" 128 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 129 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 130 | 131 | prettier@^2.2.1: 132 | version "2.2.1" 133 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" 134 | integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== 135 | 136 | source-map-support@^0.5.19: 137 | version "0.5.19" 138 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" 139 | integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== 140 | dependencies: 141 | buffer-from "^1.0.0" 142 | source-map "^0.6.0" 143 | 144 | source-map@^0.6.0: 145 | version "0.6.1" 146 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 147 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 148 | 149 | supports-color@^7.1.0: 150 | version "7.2.0" 151 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 152 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 153 | dependencies: 154 | has-flag "^4.0.0" 155 | 156 | typescript@^4.1.3: 157 | version "4.1.3" 158 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" 159 | integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== 160 | 161 | wrappy@1: 162 | version "1.0.2" 163 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 164 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 165 | --------------------------------------------------------------------------------