├── .editorconfig
├── .gitattributes
├── .gitignore
├── .gitmodules
├── .prettierrc.js
├── .vscode
└── settings.json
├── README.md
├── package.json
├── packages
├── deferred
│ ├── .gitignore
│ ├── .prettierrc.js
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── Deferred.ts
│ │ ├── main.spec.ts
│ │ └── main.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
├── either
│ ├── .gitignore
│ ├── .prettierrc.js
│ ├── LICENSE
│ ├── README.md
│ ├── examples
│ │ └── getAuthenticatedUser
│ │ │ └── getAuthenticatedUser.ts
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── Either.ts
│ │ ├── Left.spec.ts
│ │ ├── Left.ts
│ │ ├── Right.spec.ts
│ │ ├── Right.ts
│ │ ├── fromFalsy.spec.ts
│ │ ├── fromFalsy.ts
│ │ ├── fromNullish.spec.ts
│ │ ├── fromNullish.ts
│ │ ├── fromPredicate.spec.ts
│ │ ├── fromPredicate.ts
│ │ ├── index.ts
│ │ ├── isEither.spec.ts
│ │ ├── isEither.ts
│ │ ├── tryCatch.spec.ts
│ │ └── tryCatch.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
├── falsy
│ ├── .gitignore
│ ├── .prettierrc.js
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── main.spec.ts
│ │ └── main.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
├── json
│ ├── .gitignore
│ ├── .prettierrc.js
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── Json.spec.ts
│ │ ├── Json.ts
│ │ ├── ReadonlyJson.spec.ts
│ │ ├── ReadonlyJson.ts
│ │ ├── fromJSON.spec.ts
│ │ ├── fromJSON.ts
│ │ ├── main.ts
│ │ ├── toJSON.spec.ts
│ │ └── toJSON.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
├── nullish
│ ├── .gitignore
│ ├── .prettierrc.js
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── main.spec.ts
│ │ └── main.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
├── pipe
│ ├── .gitignore
│ ├── .prettierrc.js
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── pipe.spec.ts
│ │ └── pipe.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
└── predicate
│ ├── .gitignore
│ ├── .prettierrc.js
│ ├── LICENSE
│ ├── README.md
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ ├── main.spec.ts
│ └── main.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ └── tsconfig.test.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── scripts
└── bump.sh
├── tsconfig.build.json
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Settings for editors and IDEs.
2 | # References at https://editorconfig.org/.
3 |
4 | root = true
5 |
6 | # Settings for any file.
7 | [*]
8 | charset = utf-8
9 | end_of_line = lf
10 | indent_size = 2
11 | indent_style = space
12 | insert_final_newline = true
13 | trim_trailing_whitespace = true
14 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # File attributes for Git repository.
2 | # References at https://git-scm.com/docs/gitattributes.
3 |
4 | # Handle files as text and ensure Unix line endings.
5 | * text=auto eol=lf
6 |
7 | # Ignore differences on PNPM's lockfile.
8 | # Since version 5.11.0, PNPM automatically resolve its merge conflicts.
9 | pnpm-lock.yaml -diff
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node.js modules.
2 | node_modules/
3 |
4 | # Log files.
5 | *.log
6 |
7 | # Finder settings files (MacOS).
8 | .DS_Store
9 |
10 | # npm's lockfiles.
11 | # We're using pnpm and it provides its own lockfile.
12 | package-lock.json
13 | npm-shrinkwrap.json
14 |
15 | # Yarn's lockfile, Plug'n'Play, folder and settings.
16 | # We're using pnpm and it provide its own lockfile and settings.
17 | yarn.lock
18 | .pnp.*
19 | .yarn/
20 | .yarnrc
21 | .yarnrc.yaml
22 |
23 | # pnpm's lockfile.
24 | # The only allowed pnpm lockfile is the root one.
25 | **/pnpm-lock.yaml
26 | !/pnpm-lock.yaml
27 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "packages/animate"]
2 | path = packages/animate
3 | url = git@github.com:VitorLuizC/animate.git
4 | [submodule "packages/format-date"]
5 | path = packages/format-date
6 | url = git@github.com:VitorLuizC/format-date.git
7 | [submodule "packages/maybe"]
8 | path = packages/maybe
9 | url = git@github.com:VitorLuizC/maybe.git
10 | [submodule "packages/create-request"]
11 | path = packages/create-request
12 | url = git@github.com:VitorLuizC/create-request.git
13 | [submodule "packages/event-emitter"]
14 | path = packages/event-emitter
15 | url = git@github.com:VitorLuizC/event-emitter.git
16 | [submodule "packages/insist"]
17 | path = packages/insist
18 | url = git@github.com:VitorLuizC/insist.git
19 | [submodule "packages/get"]
20 | path = packages/get
21 | url = git@github.com:VitorLuizC/get.git
22 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: true,
3 | endOfLine: 'lf',
4 | printWidth: 80,
5 | singleQuote: true,
6 | trailingComma: 'all',
7 | };
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.exclude": {
3 | "packages/*/src/**/*.js": true,
4 | "packages/*/src/**/*.js.map": true,
5 | "packages/*/types/**/*.ts.map": true
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🗃 `@bitty`
2 |
3 | A mono-repository with functional programming helpers, algebraic data types, util functions, types and even some micro-frameworks in TypeScript. They were designed to support multiple environments (even older browsers and ESM Node.js).
4 |
5 | - 📦 Packages distributed in ESM, CommonJS, UMD and UMD _minified_ formats.
6 |
7 | - ⚡ Lightweight, tree-shakeable and side-effects free packages.
8 |
9 | - 🔋 Bateries included:
10 |
11 | - Little to none dependencies.
12 |
13 | - Almost every package work independently.
14 |
15 | ## Packages
16 |
17 | Package | Description
18 | ------- | -----------
19 | [`@bitty/animate`](https://github.com/VitorLuizC/animate) | Create and manage animation functions with browser's AnimationFrame API.
20 | [`@bitty/create-request`](https://github.com/VitorLuizC/create-request) | Apply interceptors to `fetch` and create a custom request function.
21 | [`@bitty/deferred`](./packages/deferred/README.md) | It provides a function to create [Deferred](https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred/README.md) objects. They contain a Promise and methods to imperatively resolve or reject it.
22 | [`@bitty/either`](./packages/either/README.md) | An algebraic data type that represents a value of one of two possible types (a disjoint union).
23 | [`@bitty/event-emitter`](https://github.com/VitorLuizC/event-emitter) | Emit and listen events in any class, object or function without messing them extending classes.
24 | [`@bitty/falsy`](./packages/falsy/README.md) | Falsy helper functions and types for TypeScript.
25 | [`@bitty/format-date`](https://github.com/VitorLuizC/format-date) | A small library (around 400 B when gziped & minified) to format JavaScript `Date` object using same tokens as moment.
26 | [`@bitty/get`](https://github.com/VitorLuizC/get) | A really small and type-safe (requires TypeScript >= 4.1.3) function, that gets a nested value from an object using a path string (like "a.b[0].d"). If value is 'undefined' or unreachable returns the placeholder instead.
27 | [`@bitty/insist`](https://github.com/VitorLuizC/insist) | Insistently runs a callback and only resolves the promise when its result is truthy.
28 | [`@bitty/json`](./packages/json/README.md) | Types and type-safe functions for JSON.
29 | [`@bitty/maybe`](https://github.com/VitorLuizC/maybe) | An algebraic data type that is a container for an optional values.
30 | [`@bitty/nullish`](./packages/nullish/README.md) | Nullish helper functions and types for TypeScript.
31 | [`@bitty/pipe`](./packages/pipe/README.md) | A pipe function to perform function composition in LTR (Left-To-Right) direction.
32 | [`@bitty/predicate`](./packages/predicate/README.md) | `Predicate` and `Refinement` types for TypeScript.
33 |
34 | ## License
35 |
36 | All the packages are released under **MIT License**.
37 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitty/root",
3 | "private": true,
4 | "scripts": {
5 | "test": "pnpm --filter ./packages run test",
6 | "build": "pnpm run build -r"
7 | },
8 | "devDependencies": {
9 | "pnpm": "^6.25.1"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/deferred/.gitignore:
--------------------------------------------------------------------------------
1 | # Bundled modules and their source-maps.
2 | dist/
3 |
4 | # Generated type declarations.
5 | types/
6 |
7 | # Transpiled modules and their source-maps.
8 | src/**/*.js
9 | src/**/*.js.map
10 |
--------------------------------------------------------------------------------
/packages/deferred/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('../../.prettierrc.js');
2 |
--------------------------------------------------------------------------------
/packages/deferred/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Vitor Luiz Cavalcanti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/deferred/README.md:
--------------------------------------------------------------------------------
1 | # `@bitty/deferred`
2 |
3 | [](https://bundlephobia.com/result?p=@bitty/deferred)
4 | [](https://bundlephobia.com/result?p=@bitty/deferred)
5 |
6 | It provides a function to create [Deferred](https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred) objects. They contain a Promise and methods to imperatively resolve or reject it.
7 |
8 | - 📦 Distributions in ESM, CommonJS, UMD and UMD _minified_ formats.
9 |
10 | - ⚡ Lightweight:
11 | - Weighs less than 1KB (min + gzip).
12 | - Tree-shakeable.
13 | - Side-effects free.
14 |
15 | - 🔋 Bateries included:
16 | - No dependencies.
17 | - Only requires `Promise`, but you can use a polyfill in unsupported environments.
18 | - Isn't based in other es2015+ features or APIs.
19 |
20 | - 🏷 Safe:
21 | - JSDocs and type declarations for IDEs and editor's autocomplete/intellisense.
22 | - Made with TypeScript as strict as possible.
23 | - Unit tests with AVA.
24 |
25 | ## Installation
26 |
27 | This library is published in the NPM registry and can be installed using any compatible package manager.
28 |
29 | ```sh
30 | npm install @bitty/deferred --save
31 |
32 | # For Yarn, use the command below.
33 | yarn add @bitty/deferred
34 | ```
35 |
36 | ### Installation from CDN
37 |
38 | This module has a UMD bundle available through JSDelivr and Unpkg CDNs.
39 |
40 | ```html
41 |
42 |
43 |
44 |
45 |
46 |
47 |
60 | ```
61 |
62 | ## Getting Stated
63 |
64 | This module default exports `createDeferred`, which is a factory function that creates `Deferred` objects.
65 |
66 | ```ts
67 | import createDeferred from '@bitty/deferred';
68 |
69 | const deferred = createDeferred();
70 | ```
71 |
72 | `Deferred` objects exposes a `Promise` and methods to reject or resolve it.
73 |
74 | ```ts
75 | import createDeferred, { Deferred } from '@bitty/deferred';
76 |
77 | let deferred: Deferred;
78 |
79 | // ...
80 |
81 | deferred.promise
82 | .then(value => console.log(`You received $ ${value.toFixed(2)}!`))
83 | .catch(reason => console.error(`Couldn't receive because of `, reason));
84 |
85 | deferred.resolve(10);
86 | //=> It logs "You received $ 50.00!" in the console.
87 |
88 | deferred.reject(new Error('The account number is invalid.'));
89 | //=> Won't log anything because promise is already resolved.
90 | ```
91 |
92 | We also export the `Deferred` interface. Which simply defines the promise property (an instance of `Promise`) and the methods that change it.
93 |
94 | ```ts
95 | interface Deferred {
96 | readonly promise: Promise;
97 | reject(reason: unknown): void;
98 | resolve(value: T | PromiseLike): void;
99 | }
100 | ```
101 |
102 | ## License
103 |
104 | Released under [MIT License](./LICENSE).
105 |
--------------------------------------------------------------------------------
/packages/deferred/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitty/deferred",
3 | "version": "0.1.0",
4 | "description": "It provides a function to create Deferred objects. They contains a Promise and methods to imperatively resolve or reject it.",
5 | "sideEffects": false,
6 | "cdn": "./dist/main.umd.min.js",
7 | "main": "./dist/main.js",
8 | "types": "./types/main.d.ts",
9 | "unpkg": "./dist/main.umd.min.js",
10 | "module": "./dist/main.esm.js",
11 | "jsdelivr": "./dist/main.umd.min.js",
12 | "umd:main": "./dist/main.umd.js",
13 | "exports": {
14 | ".": [
15 | {
16 | "import": "./dist/main.mjs",
17 | "require": "./dist/main.js",
18 | "default": "./dist/main.js"
19 | },
20 | "./dist/main.js"
21 | ]
22 | },
23 | "files": [
24 | "dist/",
25 | "types/"
26 | ],
27 | "keywords": [
28 | "deferred",
29 | "deferreds",
30 | "promise",
31 | "promises",
32 | "promises-a",
33 | "Promises/A+",
34 | "promises-aplus",
35 | "future",
36 | "futures",
37 | "resolve",
38 | "reject",
39 | "async",
40 | "asynchronous",
41 | "flow",
42 | "flow control",
43 | "typescript"
44 | ],
45 | "scripts": {
46 | "test": "pnpm run test:code-style && pnpm run test:unit",
47 | "test:transpile": "tsc --project ./tsconfig.test.json",
48 | "test:unit": "pnpm run test:transpile && ava",
49 | "test:code-style": "prettier --check \"./src/**/*.ts\"",
50 | "build": "pnpm run build:transpile && pnpm run build:bundle",
51 | "build:transpile": "tsc --project ./tsconfig.build.json",
52 | "build:bundle": "rollup --config rollup.config.js",
53 | "prepublishOnly": "pnpm run test && pnpm run build"
54 | },
55 | "repository": {
56 | "type": "git",
57 | "url": "git+https://github.com/VitorLuizC/bitty.git",
58 | "directory": "packages/deferred"
59 | },
60 | "author": {
61 | "url": "https://vitorluizc.github.io/",
62 | "name": "Vitor Luiz Cavalcanti",
63 | "email": "vitorluizc@outlook.com"
64 | },
65 | "bugs": {
66 | "url": "https://github.com/VitorLuizC/bitty/issues"
67 | },
68 | "homepage": "https://github.com/VitorLuizC/bitty/tree/master/packages/deferred",
69 | "license": "MIT",
70 | "devDependencies": {
71 | "ava": "^4.0.1",
72 | "prettier": "^2.5.1",
73 | "rollup": "^2.63.0",
74 | "rollup-plugin-terser": "^7.0.2",
75 | "typescript": "^4.5.4"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/packages/deferred/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { terser } from 'rollup-plugin-terser';
2 |
3 | /**
4 | * Creates an output options object.
5 | * @param {import('rollup').OutputOptions} options
6 | * @returns {import('rollup').OutputOptions}
7 | */
8 | const Option = (options) => ({
9 | exports: 'named',
10 | sourcemap: true,
11 | ...options,
12 | });
13 |
14 | /**
15 | * An object with all configuration for `Rollup.js`.
16 | * @type {import('rollup').RollupOptions}
17 | */
18 | const options = {
19 | input: './src/main.js',
20 | output: [
21 | Option({
22 | file: './dist/main.js',
23 | format: 'commonjs',
24 | }),
25 | Option({
26 | file: './dist/main.esm.js',
27 | format: 'esm',
28 | }),
29 | Option({
30 | file: './dist/main.mjs',
31 | format: 'esm',
32 | }),
33 | Option({
34 | file: './dist/main.umd.js',
35 | name: 'createDeferred',
36 | format: 'umd',
37 | }),
38 | Option({
39 | file: './dist/main.umd.min.js',
40 | name: 'createDeferred',
41 | format: 'umd',
42 | plugins: [terser()],
43 | }),
44 | ],
45 | };
46 |
47 | export default options;
48 |
--------------------------------------------------------------------------------
/packages/deferred/src/Deferred.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Based on the obsolete `Deferred` object, that came long before Promises/A+
3 | * spec. It's an object returned by `createdDeferred` function, that provide a
4 | * new promise along with methods to change its state.
5 | *
6 | * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred|MDN} for more information.
7 | */
8 | export default interface Deferred {
9 | readonly promise: Promise;
10 |
11 | reject(reason?: unknown): void;
12 |
13 | resolve(value: T | PromiseLike): void;
14 | }
15 |
--------------------------------------------------------------------------------
/packages/deferred/src/main.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import createDeferred from './main';
3 |
4 | test('module default exports a function', (context) => {
5 | context.is(typeof createDeferred, 'function');
6 | });
7 |
8 | test('createDeferred creates a Deferred object', (context) => {
9 | const deferred = createDeferred();
10 |
11 | context.is(typeof deferred, 'object');
12 |
13 | context.true(deferred.promise instanceof Promise);
14 |
15 | context.is(typeof deferred.reject, 'function');
16 |
17 | context.is(typeof deferred.resolve, 'function');
18 | });
19 |
20 | test('deferred.reject rejects deferred promise', async (context) => {
21 | const deferred = createDeferred();
22 |
23 | deferred.promise
24 | .then(() => {
25 | context.fail();
26 | })
27 | .catch((reason) => {
28 | context.deepEqual(reason, new Error('No reason'));
29 | });
30 |
31 | deferred.reject(new Error('No reason'));
32 | });
33 |
34 | test('deferred.resolve resolves deferred promise', async (context) => {
35 | const deferred = createDeferred();
36 |
37 | const VALUE = Math.random();
38 |
39 | deferred.promise
40 | .then((value) => {
41 | context.is(value, VALUE);
42 | })
43 | .catch(() => {
44 | context.fail();
45 | });
46 |
47 | deferred.resolve(VALUE);
48 | });
49 |
--------------------------------------------------------------------------------
/packages/deferred/src/main.ts:
--------------------------------------------------------------------------------
1 | import type Deferred from './Deferred.js';
2 |
3 | export type { Deferred };
4 |
5 | /**
6 | * Creates a `Deferred` object that provides a new promise along with methods to
7 | * change its state.
8 | * @template T
9 | * @returns {Deferred.}
10 | */
11 | export default function createDeferred(): Deferred {
12 | let reject: (reason?: unknown) => void;
13 | let resolve: (value: T | PromiseLike) => void;
14 |
15 | return {
16 | promise: new Promise((_resolve, _reject) => {
17 | reject = _reject;
18 | resolve = _resolve;
19 | }),
20 |
21 | // reject was assigned, because Promise initialization is eager (sync).
22 | // @ts-expect-error
23 | reject,
24 |
25 | // resolve was assigned, because Promise initialization is eager (sync).
26 | // @ts-expect-error
27 | resolve,
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/packages/deferred/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | // Type declaration settings
5 | "declarationDir": "./types",
6 |
7 | // ECMAScript version settings
8 | "lib": ["ES5", "ES2015.Promise"]
9 | },
10 | "include": ["./src/**/*.ts"],
11 | "exclude": ["./src/**/*.spec.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/deferred/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "lib": ["ES5", "ES2015.Promise"],
5 | "types": ["node"]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/deferred/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "CommonJS"
5 | },
6 | "exclude": []
7 | }
8 |
--------------------------------------------------------------------------------
/packages/either/.gitignore:
--------------------------------------------------------------------------------
1 | # Bundled modules and their source-maps.
2 | dist/
3 |
4 | # Generated type declarations.
5 | types/
6 |
7 | # Transpiled modules and their source-maps.
8 | src/**/*.js
9 | src/**/*.js.map
10 |
--------------------------------------------------------------------------------
/packages/either/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('../../.prettierrc.js');
2 |
--------------------------------------------------------------------------------
/packages/either/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vitor Luiz Cavalcanti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/either/README.md:
--------------------------------------------------------------------------------
1 | # `@bitty/either`
2 |
3 | ## Examples
4 |
5 | - [`getAuthenticatedUser`](./examples/getAuthenticatedUser/getAuthenticatedUser.ts) is a function used to get an authenticated user. Its a pretty common case and it was implemented in the way I think we should use `Either`.
6 |
--------------------------------------------------------------------------------
/packages/either/examples/getAuthenticatedUser/getAuthenticatedUser.ts:
--------------------------------------------------------------------------------
1 | import * as Either from '../../';
2 | // The import statement in your application would be:
3 | // import * as Either from '@bitty/either';
4 |
5 | import decodeJWT from 'jwt-decode';
6 | import isNullish from '@bitty/nullish';
7 |
8 | // ..:: Context ::..
9 |
10 | const BASE_URL = 'https://angularsp.com/api/1.0';
11 |
12 | const JWT_KEY = 'JWT';
13 |
14 | enum SignInErrorCodeEnum {
15 | JWT_NOT_FOUND = 'JWT_NOT_FOUND',
16 | JWT_INVALID = 'JWT_INVALID',
17 | JWT_EXPIRED = 'JWT_EXPIRED',
18 | CANT_GET_USER = 'CANT_GET_USER',
19 | }
20 |
21 | class SignInError extends Error {
22 | code: SignInErrorCodeEnum;
23 |
24 | constructor(code: SignInErrorCodeEnum, message = 'No message.') {
25 | super(message);
26 | this.code = code;
27 | this.name = 'JWTError';
28 | this.message = message;
29 | }
30 | }
31 |
32 | type JWTPayload = {
33 | iat: number;
34 | exp?: null | number;
35 | userId: string;
36 | };
37 |
38 | type User = {
39 | id: string;
40 | name: string;
41 | email: string;
42 | };
43 |
44 | // ..:: Business rules ::..
45 |
46 | // 1. Get persisted JWT from `window.localStorage`.
47 | // 2. With JWT, decode its payload with `jwt-decode`.
48 | // 3. With payload, check if it wasn't expired.
49 | // 4. With payload (not expired yet), get its userId.
50 | // 5. With userId, do a request to `/user`.
51 | // 6. With response, return the user.
52 |
53 | // ..:: Implementation ::..
54 |
55 | const getAuthenticatedJWT = () => {
56 | const error = new SignInError(SignInErrorCodeEnum.JWT_NOT_FOUND);
57 | return Either.fromFalsy(error)(window.localStorage.getItem(JWT_KEY));
58 | };
59 |
60 | const decodeAuthenticationJWT = (token: string) =>
61 | Either.tryCatch(
62 | () => decodeJWT(token),
63 | () => new SignInError(SignInErrorCodeEnum.JWT_INVALID),
64 | );
65 |
66 | const wasNotJWTExpired = (payload: JWTPayload) =>
67 | isNullish(payload.exp) || payload.exp > Date.now() / 1000;
68 |
69 | const checkJWTExpiration = Either.fromPredicate(wasNotJWTExpired, (payload) => {
70 | const date = new Date(payload.exp! * 1000);
71 | return new SignInError(
72 | SignInErrorCodeEnum.JWT_EXPIRED,
73 | `Authentication expired at ${date.toISOString()}`,
74 | );
75 | });
76 |
77 | const getUserById = (userId: string): Promise =>
78 | fetch(BASE_URL + '/user/' + userId, {
79 | method: 'GET',
80 | headers: {
81 | Authorization: `Bearer ${window.localStorage.getItem(JWT_KEY)!}`,
82 | },
83 | })
84 | .then((response) => response.json())
85 | .catch((error) => {
86 | const message = String(error?.message);
87 | return new SignInError(SignInErrorCodeEnum.CANT_GET_USER, message);
88 | });
89 |
90 | const getAuthenticatedUser = () =>
91 | getAuthenticatedJWT()
92 | .chain(decodeAuthenticationJWT)
93 | .chain(checkJWTExpiration)
94 | .map((payload) => payload.userId)
95 | .fold(Promise.reject, getUserById);
96 |
97 | export default getAuthenticatedUser;
98 |
--------------------------------------------------------------------------------
/packages/either/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitty/either",
3 | "version": "0.2.0",
4 | "description": "Either monad implementation.",
5 | "sideEffects": false,
6 | "cdn": "./dist/Either.umd.js",
7 | "main": "./dist/Either.js",
8 | "types": "./types/index.d.ts",
9 | "unpkg": "./dist/Either.umd.js",
10 | "module": "./dist/Either.esm.js",
11 | "jsdelivr": "./dist/Either.umd.js",
12 | "umd:main": "./dist/Either.umd.js",
13 | "exports": {
14 | ".": [
15 | {
16 | "import": "./dist/Either.mjs",
17 | "require": "./dist/Either.js",
18 | "default": "./dist/Either.js"
19 | },
20 | "./dist/Either.js"
21 | ]
22 | },
23 | "files": [
24 | "dist/",
25 | "types/"
26 | ],
27 | "keywords": [
28 | "fp",
29 | "functional programming",
30 | "function",
31 | "functional"
32 | ],
33 | "scripts": {
34 | "test": "pnpm run test:code-style && pnpm run test:unit",
35 | "test:code-style": "prettier --check \"./src/**/*.ts\"",
36 | "test:transpile": "tsc --project ./tsconfig.test.json",
37 | "test:unit": "pnpm run test:transpile && ava",
38 | "build": "pnpm run build:transpile && pnpm run build:bundle",
39 | "build:transpile": "tsc --project ./tsconfig.build.json",
40 | "build:bundle": "rollup --config rollup.config.js",
41 | "prepublishOnly": "pnpm run test && pnpm run build"
42 | },
43 | "repository": {
44 | "type": "git",
45 | "url": "git+https://github.com/VitorLuizC/bitty.git",
46 | "directory": "packages/either"
47 | },
48 | "author": {
49 | "url": "https://vitorluizc.github.io/",
50 | "name": "Vitor Luiz Cavalcanti",
51 | "email": "vitorluizc@outlook.com"
52 | },
53 | "bugs": {
54 | "url": "https://github.com/VitorLuizC/bitty/issues"
55 | },
56 | "homepage": "https://github.com/VitorLuizC/bitty/tree/master/packages/pipe",
57 | "license": "MIT",
58 | "devDependencies": {
59 | "@rollup/plugin-node-resolve": "^13.1.3",
60 | "ava": "^4.0.1",
61 | "jwt-decode": "^3.1.2",
62 | "prettier": "^2.5.1",
63 | "rollup": "^2.63.0",
64 | "rollup-plugin-terser": "^7.0.2",
65 | "typescript": "^4.5.4"
66 | },
67 | "dependencies": {
68 | "@bitty/falsy": "workspace:*",
69 | "@bitty/nullish": "workspace:*",
70 | "@bitty/predicate": "workspace:*"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/packages/either/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { terser } from 'rollup-plugin-terser';
2 | import resolve from '@rollup/plugin-node-resolve';
3 |
4 | /**
5 | * Creates an output options object.
6 | * @param {import('rollup').OutputOptions} options
7 | * @returns {import('rollup').OutputOptions}
8 | */
9 | const Option = (options) => ({
10 | exports: 'named',
11 | sourcemap: true,
12 | ...options,
13 | });
14 |
15 | /**
16 | * An object with all configuration for `Rollup.js`.
17 | * @type {import('rollup').RollupOptions}
18 | */
19 | const options = {
20 | input: './src/index.js',
21 | plugins: [resolve()],
22 | output: [
23 | Option({
24 | file: './dist/Either.js',
25 | format: 'commonjs',
26 | }),
27 | Option({
28 | file: './dist/Either.esm.js',
29 | format: 'esm',
30 | }),
31 | Option({
32 | file: './dist/Either.mjs',
33 | format: 'esm',
34 | }),
35 | Option({
36 | file: './dist/Either.umd.js',
37 | name: 'Either',
38 | format: 'umd',
39 | }),
40 | Option({
41 | file: './dist/Either.umd.min.js',
42 | name: 'Either',
43 | format: 'umd',
44 | plugins: [terser()],
45 | }),
46 | ],
47 | };
48 |
49 | export default options;
50 |
--------------------------------------------------------------------------------
/packages/either/src/Either.ts:
--------------------------------------------------------------------------------
1 | import type Left from './Left.js';
2 | import type Right from './Right.js';
3 |
4 | type Either = Left | Right;
5 |
6 | export type EitherPattern = {
7 | left: (value: L) => T;
8 | right: (value: R) => T;
9 | };
10 |
11 | export interface EitherMethods {
12 | alt(fn: () => Either): Either;
13 |
14 | map(fn: (value: R) => R2): Either;
15 |
16 | then(fn: (value: R) => R2 | Either): Either;
17 |
18 | chain(fn: (value: R) => Either): Either;
19 |
20 | mapLeft(fn: (value: L) => L2): Either;
21 |
22 | isLeft(): this is Left;
23 |
24 | isRight(): this is Right;
25 |
26 | match(pattern: EitherPattern): T;
27 |
28 | fold(onLeft: (value: L) => T, onRight: (value: R) => T): T;
29 |
30 | orElse(fn: (value: L) => Either): Either;
31 |
32 | getOrElse(fn: (value: L) => R): R;
33 |
34 | unwrap(): L | R;
35 | }
36 |
37 | export default Either;
38 |
--------------------------------------------------------------------------------
/packages/either/src/Left.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import Left from './Left.js';
3 |
4 | test('Left.unwrap returns value wrapped by `Left`', (context) => {
5 | const VALUE = Math.random();
6 | const value = Left(VALUE);
7 | context.is(value.unwrap(), VALUE);
8 | });
9 |
10 | test("Left.map don't apply function to the value", (context) => {
11 | let wasCalled = false;
12 |
13 | Left(null).map(() => {
14 | wasCalled = true;
15 | return null;
16 | });
17 |
18 | context.false(wasCalled);
19 | });
20 |
21 | test("Left.then don't apply function to the value", (context) => {
22 | let wasCalled = false;
23 |
24 | Left(null).then(() => {
25 | wasCalled = true;
26 | return null;
27 | });
28 |
29 | context.false(wasCalled);
30 | });
31 |
32 | test("Left.chain don't apply function to the value", (context) => {
33 | let wasCalled = false;
34 |
35 | Left(Math.random()).chain((value) => {
36 | wasCalled = true;
37 | return Left(value * 2);
38 | });
39 |
40 | context.false(wasCalled);
41 | });
42 |
43 | test('Left.mapLeft morphs `Left` value', (context) => {
44 | const VALUE = Math.random();
45 | const value = Left(VALUE).mapLeft((number) => number * 2);
46 |
47 | context.is(value.unwrap(), VALUE * 2);
48 | });
49 |
50 | test('Left.isLeft returns `true`', (context) => {
51 | context.true(Left(0).isLeft());
52 | });
53 |
54 | test('Left.isRight returns `false`', (context) => {
55 | context.false(Left(0).isRight());
56 | });
57 |
58 | test('Left.match morphs left value and return it', (context) => {
59 | const formatToMoney = (value: number) => `$ ${value.toFixed(2)}`;
60 |
61 | const money = Left(0).match({
62 | left: formatToMoney,
63 | right: formatToMoney,
64 | });
65 |
66 | context.is(money, '$ 0.00');
67 | });
68 |
69 | test('Left.match only call `left` leaf', (context) => {
70 | let leftWasCalled = false;
71 | let rightWasCalled = false;
72 |
73 | Left(0).match({
74 | left: () => {
75 | leftWasCalled = true;
76 | },
77 | right: () => {
78 | rightWasCalled = true;
79 | },
80 | });
81 |
82 | context.true(leftWasCalled);
83 | context.false(rightWasCalled);
84 | });
85 |
86 | test('Left.fold morphs left value and return it', (context) => {
87 | const formatToMoney = (value: number) => `$ ${value.toFixed(2)}`;
88 |
89 | const money = Left(0).fold(formatToMoney, formatToMoney);
90 |
91 | context.is(money, '$ 0.00');
92 | });
93 |
94 | test('Left.fold only call `left` function', (context) => {
95 | let leftWasCalled = false;
96 | let rightWasCalled = false;
97 |
98 | Left(0).fold(
99 | () => {
100 | leftWasCalled = true;
101 | },
102 | () => {
103 | rightWasCalled = true;
104 | },
105 | );
106 |
107 | context.true(leftWasCalled);
108 | context.false(rightWasCalled);
109 | });
110 |
111 | test('Left.getOrElse morphs value and return it', (context) => {
112 | const value = Left(new Error('Not a valid number')).getOrElse(
113 | () => 0,
114 | );
115 |
116 | context.is(value, 0);
117 | });
118 |
119 | test('Left.orElse morphs value and return a new Left', (context) => {
120 | const value = Left(new TypeError('Not a valid number')).orElse(
121 | (error) => {
122 | if (error instanceof TypeError) return Left(0);
123 | return Left(NaN);
124 | },
125 | );
126 |
127 | context.is(value.unwrap(), 0);
128 | });
129 |
--------------------------------------------------------------------------------
/packages/either/src/Left.ts:
--------------------------------------------------------------------------------
1 | import type { EitherMethods } from './Either.js';
2 |
3 | interface Left extends EitherMethods {
4 | _kind: 'Left';
5 | }
6 |
7 | /**
8 | * Creates a `Left` instance that implements `Either` methods. It generally
9 | * represents an error because `Either` is right-oriented.
10 | * @param {L} value - The value used as `Left`.
11 | * @returns {Left.}
12 | * @template L
13 | */
14 | function Left(value: L): Left {
15 | return {
16 | _kind: 'Left',
17 | alt: (fn) => fn(),
18 | map: () => Left(value),
19 | then: () => Left(value),
20 | chain: () => Left(value),
21 | mapLeft: (fn) => Left(fn(value)),
22 | isLeft: () => true,
23 | isRight: () => false,
24 | match: ({ left }) => left(value),
25 | fold: (onLeft) => onLeft(value),
26 | getOrElse: (fn) => fn(value),
27 | orElse: (fn) => fn(value),
28 | unwrap: () => value,
29 | };
30 | }
31 |
32 | export default Left;
33 |
--------------------------------------------------------------------------------
/packages/either/src/Right.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import Right from './Right.js';
3 | import Left from './Left.js';
4 |
5 | test('Right.unwrap returns value wrapped by `Right`', (context) => {
6 | const VALUE = Math.random();
7 | const value = Right(VALUE);
8 | context.is(value.unwrap(), VALUE);
9 | });
10 |
11 | test('Right.map morphs wrapped value', (context) => {
12 | const VALUE = Math.random();
13 | const value1 = Right(VALUE);
14 | const value2 = value1.map((value) => value * 2);
15 |
16 | context.is(value1.unwrap(), VALUE);
17 | context.is(value2.unwrap(), VALUE * 2);
18 | context.not(value1, value2);
19 | });
20 |
21 | test('Right.then morphs wrapped value', (context) => {
22 | const VALUE = Math.random();
23 | const value1 = Right(VALUE);
24 | const value2 = value1.then((value) => value * 2);
25 |
26 | context.is(value1.unwrap(), VALUE);
27 | context.is(value2.unwrap(), VALUE * 2);
28 | context.not(value1, value2);
29 | });
30 |
31 | test('Right.then morphs wrapped value and return a new `Right`', (context) => {
32 | const VALUE = Math.random();
33 | const value1 = Right(VALUE);
34 | const value2 = value1.then((value) => Right(value * 2));
35 |
36 | context.is(value1.unwrap(), VALUE);
37 | context.is(value2.unwrap(), VALUE * 2);
38 | context.not(value1, value2);
39 | });
40 |
41 | test('Right.chain morphs wrapped value and return a new `Right`', (context) => {
42 | const VALUE = Math.random();
43 | const value1 = Right(VALUE);
44 | const value2 = value1.chain((value) => Right(value * 2));
45 |
46 | context.is(value1.unwrap(), VALUE);
47 | context.is(value2.unwrap(), VALUE * 2);
48 | context.not(value1, value2);
49 | });
50 |
51 | test("Right.mapLeft don't apply function to the value", (context) => {
52 | let wasCalled = false;
53 |
54 | Right(1298).mapLeft(() => {
55 | wasCalled = true;
56 | return null;
57 | });
58 |
59 | context.false(wasCalled);
60 | });
61 |
62 | test('Right.mapLeft returns new `Right` with same wrapped value', (context) => {
63 | const VALUE = Math.random();
64 |
65 | const value = Right(VALUE).mapLeft(() => Math.random());
66 |
67 | context.is(value.unwrap(), VALUE);
68 | });
69 |
70 | test('Right.isLeft returns `false`', (context) => {
71 | context.false(Right(0).isLeft());
72 | });
73 |
74 | test('Right.isRight returns `true`', (context) => {
75 | context.true(Right(0).isRight());
76 | });
77 |
78 | test('Right.match morphs wrapped value and return it', (context) => {
79 | const formatToMoney = (value: number) => `$ ${value.toFixed(2)}`;
80 |
81 | const money = Right(100).match({
82 | left: formatToMoney,
83 | right: formatToMoney,
84 | });
85 |
86 | context.is(money, '$ 100.00');
87 | });
88 |
89 | test('Right.match only call `Right` leaf', (context) => {
90 | let leftWasCalled = false;
91 | let rightWasCalled = false;
92 |
93 | Right(0).match({
94 | left: () => {
95 | leftWasCalled = true;
96 | },
97 | right: () => {
98 | rightWasCalled = true;
99 | },
100 | });
101 |
102 | context.false(leftWasCalled);
103 | context.true(rightWasCalled);
104 | });
105 |
106 | test('Right.fold morphs wrapped value and return it', (context) => {
107 | const formatToMoney = (value: number) => `$ ${value.toFixed(2)}`;
108 |
109 | const money = Right(100).fold(formatToMoney, formatToMoney);
110 |
111 | context.is(money, '$ 100.00');
112 | });
113 |
114 | test('Right.fold only call `Right` function', (context) => {
115 | let leftWasCalled = false;
116 | let rightWasCalled = false;
117 |
118 | Right(0).fold(
119 | () => {
120 | leftWasCalled = true;
121 | },
122 | () => {
123 | rightWasCalled = true;
124 | },
125 | );
126 |
127 | context.false(leftWasCalled);
128 | context.true(rightWasCalled);
129 | });
130 |
131 | test('Right.getOrElse just returns wrapped value', (context) => {
132 | const VALUE = Math.random();
133 | const value = Right(VALUE).getOrElse(() => 0);
134 |
135 | context.is(value, VALUE);
136 | });
137 |
138 | test("Right.orElse don't even execute the callback", (context) => {
139 | let wasCalled = false;
140 |
141 | Right(100).orElse((error) => {
142 | wasCalled = true;
143 | if (error instanceof TypeError) return Left(0);
144 | return Left(NaN);
145 | });
146 |
147 | context.false(wasCalled);
148 | });
149 |
--------------------------------------------------------------------------------
/packages/either/src/Right.ts:
--------------------------------------------------------------------------------
1 | import type { EitherMethods } from './Either.js';
2 |
3 | import isEither from './isEither.js';
4 |
5 | interface Right extends EitherMethods {
6 | _kind: 'Right';
7 | }
8 |
9 | /**
10 | * Creates a `Right` instance that implements `Either` methods. It generally
11 | * represents an successful value because `Either` is right-oriented.
12 | * @param {R} value - The value used as `Right`.
13 | * @returns {Left.<*, R>}
14 | * @template R
15 | */
16 | function Right(value: R): Right {
17 | return {
18 | _kind: 'Right',
19 | alt: () => Right(value),
20 | map: (fn) => Right(fn(value)),
21 | then: (fn) => {
22 | const valueOrEither = fn(value);
23 | return isEither(valueOrEither) ? valueOrEither : Right(valueOrEither);
24 | },
25 | chain: (fn) => fn(value),
26 | mapLeft: () => Right(value),
27 | isLeft: () => false,
28 | isRight: () => true,
29 | match: ({ right }) => right(value),
30 | fold: (_, onRight) => onRight(value),
31 | getOrElse: () => value,
32 | orElse: () => Right(value),
33 | unwrap: () => value,
34 | };
35 | }
36 |
37 | export default Right;
38 |
--------------------------------------------------------------------------------
/packages/either/src/fromFalsy.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 |
3 | import fromFalsy from './fromFalsy.js';
4 |
5 | test('fromFalsy returns `Left` for falsy values', (context) => {
6 | const from = fromFalsy(new Error('Not defined'));
7 |
8 | context.true(from(null).isLeft());
9 | context.true(from(undefined).isLeft());
10 | context.true(from(0n).isLeft());
11 | context.true(from(-0).isLeft());
12 | context.true(from(0).isLeft());
13 | context.true(from('').isLeft());
14 | context.true(from(NaN).isLeft());
15 | context.true(from(false).isLeft());
16 | });
17 |
18 | test('fromFalsy returns `Right` for non-falsy values', (context) => {
19 | const name = fromFalsy(new Error('Not defined'))('Karl');
20 |
21 | context.true(name.isRight());
22 | });
23 |
24 | test('fromFalsy uses default value as returned `Left` for falsy values', (context) => {
25 | const DEFAULT_VALUE = Math.random();
26 |
27 | const fromNull = fromFalsy(DEFAULT_VALUE)(null);
28 |
29 | context.is(fromNull.unwrap(), DEFAULT_VALUE);
30 | });
31 |
32 | test('fromFalsy uses value as returned `Right` for non-falsy values', (context) => {
33 | const VALUE = Math.random();
34 | const value = fromFalsy(new Error('Value is not defined'))(VALUE);
35 |
36 | context.is(value.unwrap(), VALUE);
37 | });
38 |
--------------------------------------------------------------------------------
/packages/either/src/fromFalsy.ts:
--------------------------------------------------------------------------------
1 | import type Either from './Either.js';
2 |
3 | import isFalsy, { Falsy, NonFalsy } from '@bitty/falsy';
4 |
5 | import Left from './Left.js';
6 | import Right from './Right.js';
7 |
8 | /**
9 | * Receives a default value and returns a function to create `Either` instances
10 | * from values that can be falsy (`""`, `null`, `false`, `0`, `-0`, `0n`, `NaN`
11 | * or `undefined`). If so, it returns a `Left` with the received default value,
12 | * otherwise a `Right` with non-falsy value.
13 | * @param {L} defaultValue - The value used as `Left` if value is falsy.
14 | * @returns {function(R | Falsy): Either.}
15 | * @template L, R
16 | */
17 | export default function fromFalsy(defaultValue: L) {
18 | return (value?: Falsy | R): Either> =>
19 | isFalsy(value) ? Left(defaultValue) : Right(value as NonFalsy);
20 | }
21 |
--------------------------------------------------------------------------------
/packages/either/src/fromNullish.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 |
3 | import fromNullish from './fromNullish.js';
4 |
5 | test('fromNullish returns `Left` for nullish values', (context) => {
6 | const from = fromNullish(new Error('Not defined'));
7 |
8 | context.true(from().isLeft());
9 | context.true(from(null).isLeft());
10 | context.true(from(undefined).isLeft());
11 | context.true(from(undefined as void).isLeft());
12 | });
13 |
14 | test('fromNullish returns `Right` for non-nullish values', (context) => {
15 | const name = fromNullish(new Error('Not defined'))('Karl');
16 |
17 | context.true(name.isRight());
18 | });
19 |
20 | test('fromNullish uses default value as returned `Left` for nullish values', (context) => {
21 | const DEFAULT_VALUE = Math.random();
22 |
23 | const from = fromNullish(DEFAULT_VALUE);
24 |
25 | context.is(from(null).unwrap(), DEFAULT_VALUE);
26 | context.is(from(undefined).unwrap(), DEFAULT_VALUE);
27 | });
28 |
29 | test('fromNullish uses value as returned `Right` for non-nullish values', (context) => {
30 | const VALUE = Math.random();
31 | const value = fromNullish(new Error('Value is not defined'))(VALUE);
32 |
33 | context.is(value.unwrap(), VALUE);
34 | });
35 |
--------------------------------------------------------------------------------
/packages/either/src/fromNullish.ts:
--------------------------------------------------------------------------------
1 | import type Either from './Either.js';
2 |
3 | import isNullish, { Nullish, NonNullish } from '@bitty/nullish';
4 |
5 | import Left from './Left.js';
6 | import Right from './Right.js';
7 |
8 | /**
9 | * Receives a default value and returns a function to create `Either` instances
10 | * from values that can be nullish (`void`, `null` or `undefined`). If so, it
11 | * returns a `Left` with the received default value, otherwise a `Right` with
12 | * non-nullish value.
13 | * @param {L} defaultValue - The value used as `Left` if value is nullish.
14 | * @returns {function(R | Nullish): Either.}
15 | * @template L, R
16 | */
17 | export default function fromNullish(defaultValue: L) {
18 | return (value?: Nullish | R): Either> =>
19 | isNullish(value) ? Left(defaultValue) : Right(value as NonNullish);
20 | }
21 |
--------------------------------------------------------------------------------
/packages/either/src/fromPredicate.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 |
3 | import fromPredicate from './fromPredicate.js';
4 |
5 | test("fromPredicate returns `Left` if value doesn't match predicate", (context) => {
6 | const validateEven = fromPredicate(
7 | (value: number) => value % 2 === 0,
8 | (value) => value,
9 | );
10 |
11 | context.true(validateEven(1).isLeft());
12 | });
13 |
14 | test('fromPredicate returns `Right` if value matches predicate', (context) => {
15 | const validateEven = fromPredicate(
16 | (value: number) => value % 2 === 0,
17 | (value) => value,
18 | );
19 |
20 | context.true(validateEven(2).isRight());
21 | });
22 |
23 | test('fromPredicate create value returned as `Left` with `onLeft` callback', (context) => {
24 | const VALUE = Math.random();
25 |
26 | const getString = fromPredicate(
27 | (value: unknown) => typeof value === 'string',
28 | (value: unknown) => String(value),
29 | );
30 |
31 | context.is(getString(VALUE).unwrap(), String(VALUE));
32 | });
33 |
34 | test('fromPredicate uses value as returned `Right` if value matches predicate', (context) => {
35 | const VALUE = Math.random();
36 | const validateEven = fromPredicate(
37 | (value: number) => typeof value === 'number',
38 | (value) => value,
39 | );
40 |
41 | context.is(validateEven(VALUE).unwrap(), VALUE);
42 | });
43 |
--------------------------------------------------------------------------------
/packages/either/src/fromPredicate.ts:
--------------------------------------------------------------------------------
1 | import type { Predicate, Refinement } from '@bitty/predicate';
2 |
3 | import type Either from './Either.js';
4 |
5 | import Left from './Left.js';
6 | import Right from './Right.js';
7 |
8 | /**
9 | * Receives two arguments, a predicate, and the `onLeft` function, and returns a
10 | * function to create `Either` instances by checking predicate on values. If the
11 | * predicate returns true it uses the value as `Right`, otherwise it calls
12 | * `onLeft` with value and uses its result as `Left`.
13 | * @param {function(R): boolean} predicate - A predicate function.
14 | * @param {function(R): L} onLeft - A function to create value used as `Left`.
15 | * @returns {function(R): Either.}
16 | * @template L, R
17 | */
18 | export default function fromPredicate(
19 | predicate: Refinement,
20 | onLeft: (value: R) => L,
21 | ): (value: R) => Either;
22 | export default function fromPredicate(
23 | predicate: Predicate,
24 | onLeft: (value: R) => L,
25 | ): (value: R) => Either;
26 | export default function fromPredicate(predicate: Predicate, onLeft: Function) {
27 | return (value: unknown) =>
28 | predicate(value) ? Right(value) : Left(onLeft(value));
29 | }
30 |
--------------------------------------------------------------------------------
/packages/either/src/index.ts:
--------------------------------------------------------------------------------
1 | export type { default as Either } from './Either.js';
2 |
3 | export { default as fromFalsy } from './fromFalsy.js';
4 | export { default as fromNullish } from './fromNullish.js';
5 | export { default as fromPredicate } from './fromPredicate.js';
6 | export { default as tryCatch } from './tryCatch.js';
7 | export { default as Left } from './Left.js';
8 | export { default as Right } from './Right.js';
9 |
--------------------------------------------------------------------------------
/packages/either/src/isEither.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 |
3 | import isEither from './isEither.js';
4 | import Left from './Left.js';
5 | import Right from './Right.js';
6 |
7 | test('isEither returns `true` for `Left` values', (context) => {
8 | context.true(isEither(Left(new Error('Invalid argument.'))));
9 | context.true(isEither(Left('Unknown')));
10 | context.true(isEither(Left([])));
11 | });
12 |
13 | test('isEither returns `true` for `Right` values', (context) => {
14 | context.true(isEither(Right(null)));
15 | context.true(isEither(Right('Okay')));
16 | context.true(isEither(Right([1, 2, 3])));
17 | });
18 |
19 | test('isEither returns `false` for any other value', (context) => {
20 | context.false(isEither(null));
21 | context.false(isEither('Okay'));
22 | context.false(isEither({}));
23 | });
24 |
--------------------------------------------------------------------------------
/packages/either/src/isEither.ts:
--------------------------------------------------------------------------------
1 | import type Either from './Either.js';
2 |
3 | /**
4 | * Check if the value is an `Either`.
5 | * @param {*} value - Value that will be checked.
6 | * @returns {Boolean}
7 | */
8 | export default function isEither(
9 | value: unknown,
10 | ): value is Either {
11 | return (value as any)?._kind === 'Left' || (value as any)?._kind === 'Right';
12 | }
13 |
--------------------------------------------------------------------------------
/packages/either/src/tryCatch.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import tryCatch from './tryCatch.js';
3 |
4 | test('tryCatch execute function and use its return as `Right`', (context) => {
5 | const value = tryCatch(
6 | () => JSON.parse('{"name":"Karl"}'),
7 | (error) => error,
8 | );
9 |
10 | context.deepEqual(value.unwrap(), { name: 'Karl' });
11 | context.true(value.isRight());
12 | });
13 |
14 | test('tryCatch when error is thrown calls onLeft with error and returns its result as `Left`', (context) => {
15 | const value = tryCatch(
16 | () => JSON.parse('{"name":Karl}'),
17 | (error) =>
18 | new Error(
19 | error instanceof Error
20 | ? error.message
21 | : typeof error === 'string'
22 | ? error
23 | : 'Unknown error message.',
24 | ),
25 | );
26 |
27 | context.true(value.unwrap() instanceof Error);
28 | context.true(value.isLeft());
29 | });
30 |
--------------------------------------------------------------------------------
/packages/either/src/tryCatch.ts:
--------------------------------------------------------------------------------
1 | import type Either from './Either.js';
2 |
3 | import Left from './Left.js';
4 | import Right from './Right.js';
5 |
6 | /**
7 | * Receives a function that returns a value used as `Right`, if an error is
8 | * thrown it calls `onLeft` with error and returns its result as `Left`.
9 | * @param {function(): R} fn - A function that returns the value used as `Right`.
10 | * @param {function(*): L} onLeft - A function used to transform error into the value used as `Left`.
11 | * @returns {Either.}
12 | * @template L, R
13 | */
14 | export default function tryCatch(
15 | fn: () => R,
16 | onLeft: (error: unknown) => L,
17 | ): Either {
18 | try {
19 | return Right(fn());
20 | } catch (error) {
21 | return Left(onLeft(error));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/packages/either/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | // Type declaration settings
5 | "declarationDir": "./types",
6 |
7 | // ECMAScript version settings
8 | "lib": ["ES5"]
9 | },
10 | "include": ["./src/**/*.ts"],
11 | "exclude": ["./src/**/*.spec.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/either/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "target": "ESNext"
5 | },
6 | "include": ["./src/**/*.ts"]
7 | }
8 |
--------------------------------------------------------------------------------
/packages/either/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "CommonJS"
5 | },
6 | "exclude": []
7 | }
8 |
--------------------------------------------------------------------------------
/packages/falsy/.gitignore:
--------------------------------------------------------------------------------
1 | # Bundled modules and their source-maps.
2 | dist/
3 |
4 | # Generated type declarations.
5 | types/
6 |
7 | # Transpiled modules and their source-maps.
8 | src/**/*.js
9 | src/**/*.js.map
10 |
--------------------------------------------------------------------------------
/packages/falsy/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('../../.prettierrc.js');
2 |
--------------------------------------------------------------------------------
/packages/falsy/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vitor Luiz Cavalcanti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/falsy/README.md:
--------------------------------------------------------------------------------
1 | # `@bitty/falsy`
2 |
3 | [](https://bundlephobia.com/result?p=@bitty/falsy)
4 | [](https://bundlephobia.com/result?p=@bitty/falsy)
5 |
6 | Falsy helper functions and types for TypeScript.
7 |
8 | - 📦 Distributions in ESM, CommonJS, UMD and UMD _minified_ formats.
9 |
10 | - ⚡ Lightweight:
11 | - Weighs less than 0.2KB (min + gzip).
12 | - Tree-shakeable.
13 | - Side-effects free.
14 |
15 | - 🔋 Bateries included:
16 | - No dependencies.
17 | - Its not based on newer browser's APIs or es2015+ features.
18 |
19 | - 🏷 Safe:
20 | - JSDocs and type declarations for IDEs and editor's autocomplete/intellisense.
21 | - Made with TypeScript as strict as possible.
22 | - Unit tests with AVA.
23 |
24 | ## Installation
25 |
26 | This library is published in the NPM registry and can be installed using any compatible package manager.
27 |
28 | ```sh
29 | npm install @bitty/falsy --save
30 |
31 | # For Yarn, use the command below.
32 | yarn add @bitty/falsy
33 | ```
34 |
35 | ### Installation from CDN
36 |
37 | This module has a UMD bundle available through JSDelivr and Unpkg CDNs.
38 |
39 | ```html
40 |
41 |
42 |
43 |
44 |
45 |
46 |
54 | ```
55 |
56 | ## Getting Stated
57 |
58 | This module default exports `isFalsy`, which is a predicate function that checks if value is _falsy_.
59 |
60 | ```ts
61 | import isFalsy from '@bitty/pipe';
62 |
63 | isFalsy();
64 | isFalsy(null);
65 | isFalsy(undefined);
66 | isFalsy(0);
67 | isFalsy(-0);
68 | isFalsy(0n);
69 | isFalsy(NaN);
70 | isFalsy('');
71 | isFalsy(false);
72 | //=> true
73 |
74 | isFalsy('Not empty.');
75 | //=> false
76 | ```
77 |
78 | We also exports `NonFalsy` and `Falsy` types.
79 |
80 | - `Falsy` is simply an union of `false`, `void`, `''`, `0`, `0n`, `null` and `undefined`, types.
81 |
82 | ```ts
83 | import { Falsy } from '@bitty/falsy';
84 |
85 | let falsy: Falsy;
86 | falsy = false;
87 | falsy = undefined as void;
88 | falsy = '';
89 | falsy = 0;
90 | falsy = 0n;
91 | falsy = null;
92 | falsy = undefined;
93 |
94 | falsy = 1;
95 | //=> throws "Type '1' is not assignable to type 'Falsy'.".
96 | ```
97 |
98 | - `NonFalsy` is a type helper that removes _falsy_ types.
99 |
100 | ```ts
101 | import { NonFalsy } from '@bitty/falsy';
102 |
103 | type Value = 0 | 1 | 2;
104 |
105 | const value: NonFalsy = 0;
106 | //=> throws "Type '0' is not assignable to type '1 | 2'.".
107 | ```
108 |
109 | ## License
110 |
111 | Released under [MIT License](./LICENSE).
112 |
--------------------------------------------------------------------------------
/packages/falsy/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitty/falsy",
3 | "version": "0.2.0",
4 | "description": "Falsy helper functions and types for TypeScript.",
5 | "sideEffects": false,
6 | "cdn": "./dist/main.umd.js",
7 | "main": "./dist/main.js",
8 | "types": "./types/main.d.ts",
9 | "unpkg": "./dist/main.umd.js",
10 | "module": "./dist/main.esm.js",
11 | "jsdelivr": "./dist/main.umd.js",
12 | "umd:main": "./dist/main.umd.js",
13 | "exports": {
14 | ".": [
15 | {
16 | "import": "./dist/main.mjs",
17 | "require": "./dist/main.js",
18 | "default": "./dist/main.js"
19 | },
20 | "./dist/main.js"
21 | ]
22 | },
23 | "files": [
24 | "dist/",
25 | "types/"
26 | ],
27 | "keywords": [
28 | "falsy",
29 | "falsey",
30 | "false",
31 | "non-falsy",
32 | "non-falsey",
33 | "predicate",
34 | "type",
35 | "types",
36 | "type-guard",
37 | "type-predicate",
38 | "type-helper",
39 | "typescript",
40 | "typescript-types",
41 | "fp",
42 | "functional programming",
43 | "function",
44 | "functional"
45 | ],
46 | "scripts": {
47 | "test": "pnpm run test:code-style && pnpm run test:unit",
48 | "test:transpile": "tsc --project ./tsconfig.test.json",
49 | "test:unit": "pnpm run test:transpile && ava",
50 | "test:code-style": "prettier --check \"./src/**/*.ts\"",
51 | "build": "pnpm run build:transpile && pnpm run build:bundle",
52 | "build:transpile": "tsc --project ./tsconfig.build.json",
53 | "build:bundle": "rollup --config rollup.config.js",
54 | "prepublishOnly": "pnpm run test && pnpm run build"
55 | },
56 | "repository": {
57 | "type": "git",
58 | "url": "git+https://github.com/VitorLuizC/bitty.git",
59 | "directory": "packages/falsy"
60 | },
61 | "author": {
62 | "url": "https://vitorluizc.github.io/",
63 | "name": "Vitor Luiz Cavalcanti",
64 | "email": "vitorluizc@outlook.com"
65 | },
66 | "bugs": {
67 | "url": "https://github.com/VitorLuizC/bitty/issues"
68 | },
69 | "homepage": "https://github.com/VitorLuizC/bitty/tree/master/packages/falsy",
70 | "license": "MIT",
71 | "devDependencies": {
72 | "ava": "^4.0.1",
73 | "prettier": "^2.5.1",
74 | "rollup": "^2.63.0",
75 | "rollup-plugin-terser": "^7.0.2",
76 | "typescript": "^4.5.4"
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/packages/falsy/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { terser } from 'rollup-plugin-terser';
2 |
3 | /**
4 | * Creates an output options object.
5 | * @param {import('rollup').OutputOptions} options
6 | * @returns {import('rollup').OutputOptions}
7 | */
8 | const Option = (options) => ({
9 | exports: 'named',
10 | sourcemap: true,
11 | ...options,
12 | });
13 |
14 | /**
15 | * An object with all configuration for `Rollup.js`.
16 | * @type {import('rollup').RollupOptions}
17 | */
18 | const options = {
19 | input: './src/main.js',
20 | output: [
21 | Option({
22 | file: './dist/main.js',
23 | format: 'commonjs',
24 | }),
25 | Option({
26 | file: './dist/main.esm.js',
27 | format: 'esm',
28 | }),
29 | Option({
30 | file: './dist/main.mjs',
31 | format: 'esm',
32 | }),
33 | Option({
34 | file: './dist/main.umd.js',
35 | name: 'isNullish',
36 | format: 'umd',
37 | }),
38 | Option({
39 | file: './dist/main.umd.min.js',
40 | name: 'isNullish',
41 | format: 'umd',
42 | plugins: [terser()],
43 | }),
44 | ],
45 | };
46 |
47 | export default options;
48 |
--------------------------------------------------------------------------------
/packages/falsy/src/main.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import isFalsy, { Falsy, NonFalsy } from './main.js';
3 |
4 | test('isFalsy returns `true` for falsy values', (context) => {
5 | context.true(isFalsy());
6 | context.true(isFalsy(null));
7 | context.true(isFalsy(undefined));
8 | context.true(isFalsy(0));
9 | context.true(isFalsy(-0));
10 | context.true(isFalsy(0n));
11 | context.true(isFalsy(NaN));
12 | context.true(isFalsy(''));
13 | context.true(isFalsy(false));
14 | });
15 |
16 | test('isFalsy returns `false` for non-falsy values', (context) => {
17 | context.false(isFalsy([]));
18 | context.false(isFalsy({}));
19 | context.false(isFalsy('Oi'));
20 | context.false(isFalsy(10));
21 | context.false(isFalsy(true));
22 | context.false(isFalsy(Infinity));
23 | context.false(isFalsy(0.1));
24 | context.false(isFalsy(-1n));
25 | });
26 |
27 | test('Falsy type is an union of falsy types', (context) => {
28 | type Assert = A extends B ? true : false;
29 |
30 | const value01: Assert<0, Falsy> = true;
31 | const value02: Assert<0n, Falsy> = true;
32 | const value03: Assert<-0, Falsy> = true;
33 | const value04: Assert<'', Falsy> = true;
34 | const value05: Assert = true;
35 | const value06: Assert = true;
36 | const value07: Assert = true;
37 | const value08: Assert = true;
38 |
39 | context.true(value01);
40 | context.true(value02);
41 | context.true(value03);
42 | context.true(value04);
43 | context.true(value05);
44 | context.true(value06);
45 | context.true(value07);
46 | context.true(value08);
47 | });
48 |
49 | test('NonFalsy type excludes falsy types', (context) => {
50 | type Assert = A extends B ? true : false;
51 |
52 | const value01: Assert<1 | 2 | 3, NonFalsy<0 | 1 | 2 | 3>> = true;
53 | const value02: Assert> = true;
54 |
55 | context.true(value01);
56 | context.true(value02);
57 | });
58 |
--------------------------------------------------------------------------------
/packages/falsy/src/main.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Union of values that is considered false when converted to `Boolean`.
3 | * @see {@link https://developer.mozilla.org/en-US/docs/Glossary/Falsy}.
4 | * @typedef {false | void | '' | 0 | 0n | null | undefined} Falsy
5 | */
6 |
7 | /**
8 | * Union of values that is considered false when converted to `Boolean`.
9 | * @see {@link https://developer.mozilla.org/en-US/docs/Glossary/Falsy}.
10 | */
11 | export type Falsy = false | void | '' | 0 | 0n | null | undefined;
12 |
13 | /**
14 | * Exclude falsy types (`false`, `void`, `''`, `0`, `0n`, `null` & `undefined`).
15 | */
16 | export type NonFalsy = T extends Falsy ? never : T;
17 |
18 | /**
19 | * Check if value is falsy (`""`, `null`, `false`, `0`, `NaN` or `undefined`).
20 | * @param {*} value - The value that will be checked.
21 | * @returns {Boolean}
22 | */
23 | export default function isFalsy(value?: unknown): value is Falsy {
24 | return !value;
25 | }
26 |
--------------------------------------------------------------------------------
/packages/falsy/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | // Type declaration settings
5 | "declarationDir": "./types",
6 |
7 | // ECMAScript version settings
8 | "lib": ["ES5"]
9 | },
10 | "include": ["./src/**/*.ts"],
11 | "exclude": ["./src/**/*.spec.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/falsy/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "target": "ESNext"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/packages/falsy/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "CommonJS"
5 | },
6 | "exclude": []
7 | }
8 |
--------------------------------------------------------------------------------
/packages/json/.gitignore:
--------------------------------------------------------------------------------
1 | # Bundled modules and their source-maps.
2 | dist/
3 |
4 | # Generated type declarations.
5 | types/
6 |
7 | # Transpiled modules and their source-maps.
8 | src/**/*.js
9 | src/**/*.js.map
10 |
--------------------------------------------------------------------------------
/packages/json/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('../../.prettierrc.js');
2 |
--------------------------------------------------------------------------------
/packages/json/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020-2021 Vitor Luiz Cavalcanti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/json/README.md:
--------------------------------------------------------------------------------
1 | # `@bitty/json`
2 |
3 | [](https://bundlephobia.com/result?p=@bitty/json)
4 | [](https://bundlephobia.com/result?p=@bitty/json)
5 |
6 | Types and type-safe functions for JSON.
7 |
8 | - 📦 Distributions in ESM, CommonJS, UMD and UMD _minified_ formats.
9 |
10 | - ⚡ Lightweight:
11 | - Weighs less than 0.2KB (min + gzip).
12 | - Tree-shakeable.
13 | - Side-effects free.
14 |
15 | - 🔋 Batteries included:
16 | - No dependencies.
17 | - Its not based on newer browser's APIs or es2015+ features.
18 |
19 | - 🏷 Safe:
20 | - JSDocs and type declarations for IDEs and editor's autocomplete/intellisense.
21 | - Made with TypeScript as strict as possible.
22 | - Unit tests with AVA (types was also tested).
23 |
24 | ## Installation
25 |
26 | This library is published in the NPM registry and can be installed using any compatible package manager.
27 |
28 | ```sh
29 | npm install @bitty/json --save
30 |
31 | # For Yarn, use the command below.
32 | yarn add @bitty/json
33 | ```
34 |
35 | ### Installation from CDN
36 |
37 | This module has a UMD bundle available through JSDelivr and Unpkg CDNs.
38 |
39 | ```html
40 |
41 |
42 |
43 |
44 |
45 |
46 |
54 | ```
55 |
56 | ## Getting Stated
57 |
58 | This module named exports functions and types to type-safely handle JSON.
59 |
60 | ```ts
61 | import { JsonObject, toJson } from '@bitty/json';
62 |
63 | const sendJson = (obj: T) => {
64 | const json = toJson(obj);
65 | // ...
66 | };
67 |
68 | sendJson<{ names: Set }>({ ... });
69 | //=> ❌ Type 'Set' is not assignable to type 'Json'.
70 |
71 | sendJson<{ names: string[] }>({ ... });
72 | //=> ✅
73 | ```
74 |
75 | ## API
76 |
77 | #### `JsonArray`
78 |
79 | An array of `Json` values.
80 |
81 | ```ts
82 | import { JsonArray } from '@bitty/json';
83 |
84 | const answers: JsonArray = [false, 'Okay', null, { color: '#fff' }, [0,3]];
85 | ```
86 |
87 | #### `JsonObject`
88 |
89 | An object whose property keys are strings and values are `Json` values.
90 |
91 | ```ts
92 | import { JsonObject } from '@bitty/json';
93 |
94 | const response: JsonObject = {
95 | id: 36,
96 | association: null,
97 | colors: [{color: '#00f'}, {color: '#d7a'}],
98 | isDisabled: true
99 | };
100 | ```
101 |
102 | #### `Json`
103 |
104 | A union of `null`, `boolean`, `number`, `string`, `JsonArray` and `JsonObject` types.
105 |
106 | ```ts
107 | import { Json } from '@bitty/json';
108 |
109 | const response: Json = {
110 | latest: undefined, // ❌ Type 'undefined' is not assignable to type 'Json'.
111 | current: [
112 | {
113 | name: 'Orange',
114 | color: '#ff8721',
115 | score: 2871,
116 | disabled: true,
117 | }
118 | ]
119 | };
120 | ```
121 |
122 | #### `parseJson`
123 |
124 | Converts a valid JSON string into a value, whose type that extends `Json`.
125 |
126 | ```ts
127 | import { parseJson } from '@bitty/json';
128 |
129 | type User = {
130 | name: string;
131 | };
132 |
133 | const user = parseJson('{"name":"Carlos Marcos"}');
134 | ```
135 |
136 | #### `toJson`
137 |
138 | Converts a value, whose type extends `Json`, to value to JSON string.
139 |
140 | ```ts
141 | import { toJson } from '@bitty/json';
142 |
143 | type User = {
144 | name: string;
145 | };
146 |
147 | const user = toJson({
148 | name: 'Carlos Marcos'
149 | }, 0);
150 | //=> "{\"name\":\"Carlos Marcos\"}"
151 | ```
152 |
153 | ## License
154 |
155 | Released under [MIT License](./LICENSE).
156 |
--------------------------------------------------------------------------------
/packages/json/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitty/json",
3 | "version": "0.2.0",
4 | "description": "Types and type-safe functions for JSON.",
5 | "sideEffects": false,
6 | "cdn": "./dist/json.umd.js",
7 | "main": "./dist/json.js",
8 | "types": "./types/main.d.ts",
9 | "unpkg": "./dist/json.umd.js",
10 | "module": "./dist/json.esm.js",
11 | "jsdelivr": "./dist/json.umd.js",
12 | "umd:main": "./dist/json.umd.js",
13 | "exports": {
14 | ".": [
15 | {
16 | "import": "./dist/json.mjs",
17 | "require": "./dist/json.js",
18 | "default": "./dist/json.js"
19 | },
20 | "./dist/json.js"
21 | ]
22 | },
23 | "files": [
24 | "dist/",
25 | "types/"
26 | ],
27 | "keywords": [
28 | "json",
29 | "json-types",
30 | "types",
31 | "json-typescript",
32 | "typescript-json",
33 | "typescript",
34 | "type-safe",
35 | "type-safe-json",
36 | "json-parse",
37 | "fp",
38 | "functional programming",
39 | "function",
40 | "functional"
41 | ],
42 | "scripts": {
43 | "test": "pnpm run lint && pnpm run test:unit",
44 | "lint": "prettier --check \"./src/**/*.ts\"",
45 | "lint:fix": "prettier --write \"./src/**/*.ts\"",
46 | "test:transpile": "tsc --project ./tsconfig.test.json",
47 | "test:unit": "pnpm run test:transpile && ava",
48 | "build": "pnpm run build:transpile && pnpm run build:bundle",
49 | "build:transpile": "tsc --project ./tsconfig.build.json",
50 | "build:bundle": "rollup --config rollup.config.js",
51 | "prepublishOnly": "pnpm run test && pnpm run build"
52 | },
53 | "repository": {
54 | "type": "git",
55 | "url": "git+https://github.com/VitorLuizC/bitty.git",
56 | "directory": "packages/json"
57 | },
58 | "author": {
59 | "url": "https://vitorluizc.github.io/",
60 | "name": "Vitor Luiz Cavalcanti",
61 | "email": "vitorluizc@outlook.com"
62 | },
63 | "bugs": {
64 | "url": "https://github.com/VitorLuizC/bitty/issues"
65 | },
66 | "homepage": "https://github.com/VitorLuizC/bitty/tree/master/packages/pipe",
67 | "license": "MIT",
68 | "devDependencies": {
69 | "ava": "^4.0.1",
70 | "prettier": "^2.5.1",
71 | "rollup": "^2.63.0",
72 | "rollup-plugin-terser": "^7.0.2",
73 | "typescript": "^4.5.4"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/packages/json/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { terser } from 'rollup-plugin-terser';
2 |
3 | /**
4 | * Creates an output options object.
5 | * @param {import('rollup').OutputOptions} options
6 | * @returns {import('rollup').OutputOptions}
7 | */
8 | const Option = (options) => ({
9 | exports: 'named',
10 | sourcemap: true,
11 | ...options,
12 | });
13 |
14 | /**
15 | * An object with all configuration for `Rollup.js`.
16 | * @type {import('rollup').RollupOptions}
17 | */
18 | const options = {
19 | input: './src/main.js',
20 | output: [
21 | Option({
22 | file: './dist/json.js',
23 | format: 'commonjs',
24 | }),
25 | Option({
26 | file: './dist/json.esm.js',
27 | format: 'esm',
28 | }),
29 | Option({
30 | file: './dist/json.mjs',
31 | format: 'esm',
32 | }),
33 | Option({
34 | file: './dist/json.umd.js',
35 | name: 'Json',
36 | format: 'umd',
37 | }),
38 | Option({
39 | file: './dist/json.umd.min.js',
40 | name: 'Json',
41 | format: 'umd',
42 | plugins: [terser()],
43 | }),
44 | ],
45 | };
46 |
47 | export default options;
48 |
--------------------------------------------------------------------------------
/packages/json/src/Json.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import type { Json, JsonArray, JsonObject, JsonPrimitive } from './Json.js';
3 |
4 | type Assert = T extends Expected ? true : false;
5 |
6 | test("Json matches 'JsonPrimitive', 'JsonArray' and 'JsonObject'", (context) => {
7 | const valid_00: Assert = true;
8 | const valid_01: Assert = true;
9 | const valid_02: Assert = true;
10 | const valid_03: Assert = true;
11 | const valid_04: Assert = true;
12 | const valid_05: Assert<1917, Json> = true;
13 | const valid_06: Assert = true;
14 | const valid_07: Assert<'JSON is better than XML', Json> = true;
15 | const valid_08: Assert = true;
16 | const valid_09: Assert<['JSON', 1999, boolean[]], Json> = true;
17 | const valid_10: Assert = true;
18 | const valid_11: Assert<
19 | {
20 | name: string;
21 | stats: {
22 | A: number;
23 | };
24 | records: null | string[];
25 | },
26 | Json
27 | > = true;
28 |
29 | context.true(valid_00);
30 | context.true(valid_01);
31 | context.true(valid_02);
32 | context.true(valid_03);
33 | context.true(valid_04);
34 | context.true(valid_05);
35 | context.true(valid_06);
36 | context.true(valid_07);
37 | context.true(valid_08);
38 | context.true(valid_09);
39 | context.true(valid_10);
40 | context.true(valid_11);
41 | });
42 |
43 | test("Json doesn't match invalid JSON types", (context) => {
44 | const valid_1: Assert = false;
45 | const valid_2: Assert = false;
46 | const valid_3: Assert = false;
47 | const valid_4: Assert, Json> = false;
48 | const valid_5: Assert = false;
49 | const valid_6: Assert<() => void, Json> = false;
50 |
51 | context.false(valid_1);
52 | context.false(valid_2);
53 | context.false(valid_3);
54 | context.false(valid_4);
55 | context.false(valid_5);
56 | context.false(valid_6);
57 | });
58 |
59 | test('JsonArray matches an array of primitive JSON types', (context) => {
60 | const valid: Assert<(null | number | string | boolean)[], JsonArray> = true;
61 |
62 | context.true(valid);
63 | });
64 |
65 | test("JsonArray doesn't match arrays of non-JSON types", (context) => {
66 | const valid_0: Assert = false;
67 | const valid_1: Assert = false;
68 | const valid_2: Assert<(number | undefined)[], JsonArray> = false;
69 |
70 | context.false(valid_0);
71 | context.false(valid_1);
72 | context.false(valid_2);
73 | });
74 |
75 | test("JsonArray doesn't match non array", (context) => {
76 | const valid: Assert = false;
77 |
78 | context.false(valid);
79 | });
80 |
81 | test('JsonObject matches an object with primitive JSON types', (context) => {
82 | const valid: Assert<
83 | {
84 | name: null | string;
85 | email: string;
86 | createdAt: number;
87 | isDisabled: boolean;
88 | },
89 | JsonObject
90 | > = true;
91 |
92 | context.true(valid);
93 | });
94 |
95 | test("JsonObject doesn't match objects of non-JSON types", (context) => {
96 | const valid_0: Assert<{ value: bigint }, JsonObject> = false;
97 | const valid_1: Assert<{ id: symbol }, JsonObject> = false;
98 | const valid_2: Assert<{ name?: string }[], JsonObject> = false;
99 |
100 | context.false(valid_0);
101 | context.false(valid_1);
102 | context.false(valid_2);
103 | });
104 |
105 | test("JsonObject doesn't match non object", (context) => {
106 | const valid: Assert = false;
107 |
108 | context.false(valid);
109 | });
110 |
111 | test("JsonPrimitive matches 'null'", (context) => {
112 | const valid: Assert = true;
113 |
114 | context.true(valid);
115 | });
116 |
117 | test("JsonPrimitive matches 'boolean' and its sub-types", (context) => {
118 | const valid_0: Assert = true;
119 | const valid_1: Assert = true;
120 | const valid_2: Assert = true;
121 |
122 | context.true(valid_0);
123 | context.true(valid_1);
124 | context.true(valid_2);
125 | });
126 |
127 | test("JsonPrimitive matches 'number' and its sub-types", (context) => {
128 | const valid_0: Assert = true;
129 | const valid_1: Assert<1917, JsonPrimitive> = true;
130 |
131 | context.true(valid_0);
132 | context.true(valid_1);
133 | });
134 |
135 | test("JsonPrimitive matches 'string' and its sub-types", (context) => {
136 | const valid_0: Assert = true;
137 | const valid_1: Assert<'JSON is better than XML', JsonPrimitive> = true;
138 |
139 | context.true(valid_0);
140 | context.true(valid_1);
141 | });
142 |
143 | test("JsonPrimitive doesn't match 'undefined' and its sub-type 'void'", (context) => {
144 | const valid_0: Assert = false;
145 | const valid_1: Assert = false;
146 |
147 | context.false(valid_0);
148 | context.false(valid_1);
149 | });
150 |
151 | test("JsonPrimitive doesn't match 'bigint' and its sub-types", (context) => {
152 | const valid_0: Assert = false;
153 | const valid_1: Assert<9999999999999999999999n, JsonPrimitive> = false;
154 |
155 | context.false(valid_0);
156 | context.false(valid_1);
157 | });
158 |
159 | test("JsonPrimitive doesn't match 'symbol'", (context) => {
160 | const valid: Assert = false;
161 |
162 | context.false(valid);
163 | });
164 |
--------------------------------------------------------------------------------
/packages/json/src/Json.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * An union between primitive types (`null`, `boolean`, `number` and `string`) supported by JSON.
3 | */
4 | type JsonPrimitive = null | boolean | number | string;
5 |
6 | /**
7 | * An union between {@link JsonPrimitive}, {@link JsonArray} and {@link JsonObject}.
8 | */
9 | type Json = JsonPrimitive | JsonArray | JsonObject;
10 |
11 | /**
12 | * An array of {@link Json} elements.
13 | */
14 | type JsonArray = Json[];
15 |
16 | /**
17 | * An object whose property keys are strings and values are {@link Json}.
18 | */
19 | type JsonObject = {
20 | [key: string]: Json;
21 | };
22 |
23 | export type { Json, JsonArray, JsonObject, JsonPrimitive };
24 |
--------------------------------------------------------------------------------
/packages/json/src/ReadonlyJson.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import type { Json, JsonArray, JsonObject, JsonPrimitive } from './Json.js';
3 | import type {
4 | ReadonlyJson,
5 | ReadonlyJsonArray,
6 | ReadonlyJsonObject,
7 | } from './ReadonlyJson.js';
8 |
9 | type Assert = T extends Expected ? true : false;
10 |
11 | test("ReadonlyJson matches 'Json'", (context) => {
12 | const valid: Assert = true;
13 |
14 | context.true(valid);
15 | });
16 |
17 | test('ReadonlyJson defines a read-only JSON type', (context) => {
18 | const user: ReadonlyJson = {
19 | name: 'Vitor',
20 | items: [
21 | {
22 | name: 'Magic Long Sword',
23 | },
24 | ],
25 | };
26 |
27 | // @ts-expect-error
28 | user.name = 'William';
29 |
30 | // @ts-expect-error
31 | delete user.items[0];
32 |
33 | // @ts-expect-error
34 | user.items.push({
35 | name: 'Magic Hat',
36 | });
37 |
38 | context.pass();
39 | });
40 |
41 | test("ReadonlyJson matches 'PrimitiveJson', 'ReadonlyJsonArray' and 'ReadonlyJsonObject'", (context) => {
42 | const valid_0: Assert = true;
43 | const valid_1: Assert = true;
44 | const valid_2: Assert = true;
45 |
46 | context.true(valid_0);
47 | context.true(valid_1);
48 | context.true(valid_2);
49 | });
50 |
51 | test("ReadonlyJsonArray matches 'JsonArray'", (context) => {
52 | const valid: Assert = true;
53 |
54 | context.true(valid);
55 | });
56 |
57 | test('ReadonlyJsonArray defines a read-only JSON array', (context) => {
58 | const items: ReadonlyJsonArray = [
59 | {
60 | name: 'Magic Long Sword',
61 | },
62 | ];
63 |
64 | // @ts-expect-error
65 | items.splice(0);
66 |
67 | // @ts-expect-error
68 | items.push({
69 | name: 'Axe',
70 | });
71 |
72 | context.pass();
73 | });
74 |
75 | test("ReadonlyJsonObject matches 'JsonObject'", (context) => {
76 | const valid: Assert = true;
77 |
78 | context.true(valid);
79 | });
80 |
81 | test('ReadonlyJsonObject defines a read-only JSON object', (context) => {
82 | const user: ReadonlyJsonObject = {
83 | name: 'Lord Haxz',
84 | level: 9,
85 | };
86 |
87 | // @ts-expect-error
88 | user.level = 99;
89 |
90 | // @ts-expect-error
91 | delete user.name;
92 |
93 | context.pass();
94 | });
95 |
--------------------------------------------------------------------------------
/packages/json/src/ReadonlyJson.ts:
--------------------------------------------------------------------------------
1 | import type { JsonPrimitive } from './Json';
2 |
3 | /**
4 | * An union between {@link JsonPrimitive}, {@link ReadonlyJsonArray} and {@link ReadonlyJsonObject}.
5 | */
6 | type ReadonlyJson = JsonPrimitive | ReadonlyJsonArray | ReadonlyJsonObject;
7 |
8 | /**
9 | * A read-only array with {@link ReadonlyJson} elements.
10 | */
11 | type ReadonlyJsonArray = readonly ReadonlyJson[];
12 |
13 | /**
14 | * An object with read-only properties whose keys are strings and values are {@link ReadonlyJson}.
15 | */
16 | type ReadonlyJsonObject = {
17 | readonly [key: string]: ReadonlyJson;
18 | };
19 |
20 | export type { ReadonlyJson, ReadonlyJsonArray, ReadonlyJsonObject };
21 |
--------------------------------------------------------------------------------
/packages/json/src/fromJSON.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import fromJSON from './fromJSON.js';
3 |
4 | test("fromJSON parses JSON string to 'Json'", (context) => {
5 | const expected = {
6 | name: 'Santos Dumont',
7 | };
8 |
9 | context.deepEqual(
10 | fromJSON<{ name: string }>('{ "name": "Santos Dumont" }'),
11 | expected,
12 | );
13 | });
14 |
--------------------------------------------------------------------------------
/packages/json/src/fromJSON.ts:
--------------------------------------------------------------------------------
1 | import type { Json } from './Json.js';
2 |
3 | /**
4 | * Transforms (parses) a JSON string to {@link Json} value.
5 | * @example
6 | * ```ts
7 | * type User = {
8 | * name: string;
9 | * };
10 | *
11 | * const user = fromJSON('{"name":"Carlos Marcos"}');
12 | * //=> { name: 'Carlos Marcos' }
13 | * ```
14 | * @param json - The JSON string.
15 | */
16 | function fromJSON(json: string): T {
17 | return JSON.parse(json);
18 | }
19 |
20 | export default fromJSON;
21 |
--------------------------------------------------------------------------------
/packages/json/src/main.ts:
--------------------------------------------------------------------------------
1 | export * from './Json.js';
2 | export * from './ReadonlyJson.js';
3 | export { default as fromJSON } from './fromJSON.js';
4 | export { default as toJSON } from './toJSON.js';
5 |
--------------------------------------------------------------------------------
/packages/json/src/toJSON.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import toJSON from './toJSON.js';
3 |
4 | test('toJSON transforms Json value to JSON string', (context) => {
5 | type User = {
6 | name: string;
7 | };
8 |
9 | const user: User = {
10 | name: 'Santos Dumont',
11 | };
12 |
13 | context.is(toJSON(user, 0), `{"name":"Santos Dumont"}`);
14 | });
15 |
--------------------------------------------------------------------------------
/packages/json/src/toJSON.ts:
--------------------------------------------------------------------------------
1 | import type { ReadonlyJson } from './ReadonlyJson.js';
2 |
3 | /**
4 | * Transforms a {@link Json} value to JSON string.
5 | * @example
6 | * ```ts
7 | * type User = {
8 | * name: string;
9 | * };
10 | *
11 | * const user: User = {
12 | * name: 'Karl Marx',
13 | * };
14 | *
15 | * toJson(user, 0);
16 | * //=> '{"name":"Karl Marx"}'
17 | * ```
18 | * @param value - A {@link ReadonlyJson} value, usually an object or array.
19 | * @param space - A character or the number of spaces used for indentation.
20 | */
21 | function toJSON(value: ReadonlyJson, space: string | number = 2): string {
22 | return JSON.stringify(value, null, space);
23 | }
24 |
25 | export default toJSON;
26 |
--------------------------------------------------------------------------------
/packages/json/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | // Type declaration settings
5 | "declarationDir": "./types",
6 |
7 | // ECMAScript version settings
8 | "lib": ["ES5"]
9 | },
10 | "include": ["./src/**/*.ts"],
11 | "exclude": ["./src/**/*.spec.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/json/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "lib": ["ESNext"]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/packages/json/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | // Transpile output settings
5 | "module": "CommonJS",
6 | "target": "ESNext",
7 |
8 | // Type declaration settings
9 | "declaration": false
10 | },
11 | "include": ["./test/**/*.spec.ts", "./src"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/nullish/.gitignore:
--------------------------------------------------------------------------------
1 | # Bundled modules and their source-maps.
2 | dist/
3 |
4 | # Generated type declarations.
5 | types/
6 |
7 | # Transpiled modules and their source-maps.
8 | src/**/*.js
9 | src/**/*.js.map
10 |
--------------------------------------------------------------------------------
/packages/nullish/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('../../.prettierrc.js');
2 |
--------------------------------------------------------------------------------
/packages/nullish/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vitor Luiz Cavalcanti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/nullish/README.md:
--------------------------------------------------------------------------------
1 | # `@bitty/nullish`
2 |
3 | [](https://bundlephobia.com/result?p=@bitty/nullish)
4 | [](https://bundlephobia.com/result?p=@bitty/nullish)
5 |
6 | Nullish helper functions and types for TypeScript.
7 |
8 | - 📦 Distributions in ESM, CommonJS, UMD and UMD _minified_ formats.
9 |
10 | - ⚡ Lightweight:
11 | - Weighs less than 0.2KB (min + gzip).
12 | - Tree-shakeable.
13 | - Side-effects free.
14 |
15 | - 🔋 Bateries included:
16 | - No dependencies.
17 | - Its not based on newer browser's APIs or es2015+ features.
18 |
19 | - 🏷 Safe:
20 | - JSDocs and type declarations for IDEs and editor's autocomplete/intellisense.
21 | - Made with TypeScript as strict as possible.
22 | - Unit tests with AVA.
23 |
24 | ## Installation
25 |
26 | This library is published in the NPM registry and can be installed using any compatible package manager.
27 |
28 | ```sh
29 | npm install @bitty/nullish --save
30 |
31 | # For Yarn, use the command below.
32 | yarn add @bitty/nullish
33 | ```
34 |
35 | ### Installation from CDN
36 |
37 | This module has a UMD bundle available through JSDelivr and Unpkg CDNs.
38 |
39 | ```html
40 |
41 |
42 |
43 |
44 |
45 |
46 |
54 | ```
55 |
56 | ## Getting Stated
57 |
58 | This module default exports `isNullish`, which is a predicate function that checks if value is _nullish_.
59 |
60 | ```ts
61 | import isNullish from '@bitty/pipe';
62 |
63 | isNullish(null);
64 | //=> true
65 |
66 | isNullish(undefined);
67 | //=> true
68 |
69 | isNullish(undefined as void);
70 | //=> true
71 |
72 | isNullish(NaN);
73 | //=> false
74 | ```
75 |
76 | We also exports `NonNullish` and `Nullish` types.
77 |
78 | - `Nullish` is simply an union of `null`, `void` and `undefined` types.
79 |
80 | ```ts
81 | import { Nullish } from '@bitty/nullish';
82 |
83 | let nullish: Nullish;
84 | nullish = null;
85 | nullish = undefined;
86 | nullish = undefined as void;
87 |
88 | nullish = false;
89 | //=> throws "Type 'false' is not assignable to type 'Nullish'.".
90 | ```
91 |
92 | - `NonNullish` is a type helper that removes _nullish_ types.
93 |
94 | ```ts
95 | import { NonNullish } from '@bitty/nullish';
96 |
97 | type Value = string | null | undefined;
98 |
99 | const value: NonNullish = null;
100 | //=> throws "Type 'null' is not assignable to type 'string'.".
101 | ```
102 |
103 | ## License
104 |
105 | Released under [MIT License](./LICENSE).
106 |
--------------------------------------------------------------------------------
/packages/nullish/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitty/nullish",
3 | "version": "0.2.0",
4 | "description": "Nullish helper functions and types for TypeScript.",
5 | "sideEffects": false,
6 | "cdn": "./dist/main.umd.min.js",
7 | "main": "./dist/main.js",
8 | "types": "./types/main.d.ts",
9 | "unpkg": "./dist/main.umd.min.js",
10 | "module": "./dist/main.esm.js",
11 | "jsdelivr": "./dist/main.umd.min.js",
12 | "umd:main": "./dist/main.umd.js",
13 | "exports": {
14 | ".": [
15 | {
16 | "import": "./dist/main.mjs",
17 | "require": "./dist/main.js",
18 | "default": "./dist/main.js"
19 | },
20 | "./dist/main.js"
21 | ]
22 | },
23 | "files": [
24 | "dist/",
25 | "types/"
26 | ],
27 | "keywords": [
28 | "null",
29 | "undefined",
30 | "nully",
31 | "nullable",
32 | "non-nullable",
33 | "predicate",
34 | "type",
35 | "types",
36 | "type-guard",
37 | "type-predicate",
38 | "type-helper",
39 | "typescript",
40 | "typescript-types",
41 | "fp",
42 | "functional programming",
43 | "function",
44 | "functional"
45 | ],
46 | "scripts": {
47 | "test": "pnpm run test:code-style && pnpm run test:unit",
48 | "test:transpile": "tsc --project ./tsconfig.test.json",
49 | "test:unit": "pnpm run test:transpile && ava",
50 | "test:code-style": "prettier --check \"./src/**/*.ts\"",
51 | "build": "pnpm run build:transpile && pnpm run build:bundle",
52 | "build:transpile": "tsc --project ./tsconfig.build.json",
53 | "build:bundle": "rollup --config rollup.config.js",
54 | "prepublishOnly": "pnpm run test && pnpm run build"
55 | },
56 | "repository": {
57 | "type": "git",
58 | "url": "git+https://github.com/VitorLuizC/bitty.git",
59 | "directory": "packages/nullish"
60 | },
61 | "author": {
62 | "url": "https://vitorluizc.github.io/",
63 | "name": "Vitor Luiz Cavalcanti",
64 | "email": "vitorluizc@outlook.com"
65 | },
66 | "bugs": {
67 | "url": "https://github.com/VitorLuizC/bitty/issues"
68 | },
69 | "homepage": "https://github.com/VitorLuizC/bitty/tree/master/packages/pipe",
70 | "license": "MIT",
71 | "devDependencies": {
72 | "ava": "^4.0.1",
73 | "prettier": "^2.5.1",
74 | "rollup": "^2.63.0",
75 | "rollup-plugin-terser": "^7.0.2",
76 | "typescript": "^4.5.4"
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/packages/nullish/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { terser } from 'rollup-plugin-terser';
2 |
3 | /**
4 | * Creates an output options object.
5 | * @param {import('rollup').OutputOptions} options
6 | * @returns {import('rollup').OutputOptions}
7 | */
8 | const Option = (options) => ({
9 | exports: 'named',
10 | sourcemap: true,
11 | ...options,
12 | });
13 |
14 | /**
15 | * An object with all configuration for `Rollup.js`.
16 | * @type {import('rollup').RollupOptions}
17 | */
18 | const options = {
19 | input: './src/main.js',
20 | output: [
21 | Option({
22 | file: './dist/main.js',
23 | format: 'commonjs',
24 | }),
25 | Option({
26 | file: './dist/main.esm.js',
27 | format: 'esm',
28 | }),
29 | Option({
30 | file: './dist/main.mjs',
31 | format: 'esm',
32 | }),
33 | Option({
34 | file: './dist/main.umd.js',
35 | name: 'isNullish',
36 | format: 'umd',
37 | }),
38 | Option({
39 | file: './dist/main.umd.min.js',
40 | name: 'isNullish',
41 | format: 'umd',
42 | plugins: [terser()],
43 | }),
44 | ],
45 | };
46 |
47 | export default options;
48 |
--------------------------------------------------------------------------------
/packages/nullish/src/main.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import isNullish from './main.js';
3 |
4 | test('isNullish returns `true` for nullish values', (context) => {
5 | context.true(isNullish());
6 | context.true(isNullish(null));
7 | context.true(isNullish(undefined));
8 | });
9 |
10 | test('isNullish returns `false` for non-nullish value', (context) => {
11 | context.false(isNullish('Okay'));
12 | context.false(isNullish({ name: 'Karl Marx' }));
13 | context.false(isNullish(true));
14 | context.false(isNullish(1917));
15 | });
16 |
17 | test('isNullish returns `false` even for falsy non-nullish values', (context) => {
18 | context.false(isNullish(''));
19 | context.false(isNullish(NaN));
20 | context.false(isNullish(false));
21 | context.false(isNullish(0));
22 | });
23 |
--------------------------------------------------------------------------------
/packages/nullish/src/main.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Nullish is an union of `void`, `null` and `undefined` types.
3 | */
4 | export type Nullish = void | null | undefined;
5 |
6 | /**
7 | * Exclude nullish types (`void`, `null` and `undefined`) from T.
8 | */
9 | export type NonNullish = T extends Nullish ? never : T;
10 |
11 | /**
12 | * Check if value is nullish (`void`, `null` or `undefined`).
13 | * @param {*} value - Value that will be checked.
14 | * @returns {Boolean}
15 | */
16 | export default function isNullish(value?: unknown): value is Nullish {
17 | return value == null;
18 | }
19 |
--------------------------------------------------------------------------------
/packages/nullish/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | // Type declaration settings
5 | "declarationDir": "./types",
6 |
7 | // ECMAScript version settings
8 | "lib": ["ES5"]
9 | },
10 | "include": ["./src/**/*.ts"],
11 | "exclude": ["./src/**/*.spec.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/nullish/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/nullish/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "CommonJS"
5 | },
6 | "exclude": []
7 | }
8 |
--------------------------------------------------------------------------------
/packages/pipe/.gitignore:
--------------------------------------------------------------------------------
1 | # Bundled modules and their source-maps.
2 | dist/
3 |
4 | # Generated type declarations.
5 | types/
6 |
7 | # Transpiled modules and their source-maps.
8 | src/**/*.js
9 | src/**/*.js.map
10 |
--------------------------------------------------------------------------------
/packages/pipe/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('../../.prettierrc.js');
2 |
--------------------------------------------------------------------------------
/packages/pipe/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vitor Luiz Cavalcanti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/pipe/README.md:
--------------------------------------------------------------------------------
1 | # `@bitty/pipe`
2 |
3 | [](https://bundlephobia.com/result?p=@bitty/pipe)
4 | [](https://bundlephobia.com/result?p=@bitty/pipe)
5 |
6 | A pipe function to perform function composition in LTR (Left-To-Right) direction.
7 |
8 | - 📦 Distributions in ESM, CommonJS, UMD and UMD _minified_ formats.
9 |
10 | - ⚡ Lightweight:
11 | - Weighs less than 0.3KB (min + gzip).
12 | - 3x smaller than `ramda.pipe`.
13 | - Tree-shakeable.
14 | - Side-effects free.
15 |
16 | - 🔋 Bateries included:
17 | - No dependencies.
18 | - Its not based on newer browser's APIs or es2015+ features.
19 |
20 | - 🏷 Safe:
21 | - JSDocs and type declarations for IDEs and editor's autocomplete/intellisense.
22 | - Made with TypeScript as strict as possible.
23 | - Unit tests with AVA.
24 |
25 | ## Installation
26 |
27 | This library is published in the NPM registry and can be installed using any compatible package manager.
28 |
29 | ```sh
30 | npm install @bitty/pipe --save
31 |
32 | # For Yarn, use the command below.
33 | yarn add @bitty/pipe
34 | ```
35 |
36 | ### Installation from CDN
37 |
38 | This module has a UMD bundle available through JSDelivr and Unpkg CDNs.
39 |
40 | ```html
41 |
42 |
43 |
44 |
45 |
46 |
47 |
52 | ```
53 |
54 | ## Getting Started
55 |
56 | Import `pipe` from package and just compose your functions with it.
57 |
58 | ```ts
59 | import pipe from '@bitty/pipe';
60 |
61 | const resolveToNumber = pipe(
62 | (value: unknown) => typeof value === 'number' ? value : parseFloat(value),
63 | (value: number) => Number.isNaN(value) ? 0 : value,
64 | );
65 |
66 | resolveToNumber('12389');
67 | //=> 12389
68 | ```
69 |
70 | The first pipe argument is an arity N function, so you can receive more than one argument in the composition.
71 |
72 | ```ts
73 | import pipe from '@bitty/pipe';
74 |
75 | const fromTextToWords = (text: string, wordsToIgnore: string[] = []) =>
76 | text
77 | .trim()
78 | .split(/\s+/)
79 | .filter((word) => !wordsToIgnore.includes(word));
80 |
81 | const formatToInitials = pipe(
82 | fromTextToWords,
83 | (words) => words.map((word) => word.charAt(0)),
84 | (initials) => initials.join('').toUpperCase(),
85 | );
86 |
87 | formatToInitials('abraão william de santana ', ['de']);
88 | //=> "AWS"
89 | ```
90 |
91 | ## License
92 |
93 | Released under [MIT License](./LICENSE).
94 |
--------------------------------------------------------------------------------
/packages/pipe/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitty/pipe",
3 | "version": "0.3.0",
4 | "description": "A pipe function to perform function composition in LTR (Left To Right) direction.",
5 | "sideEffects": false,
6 | "cdn": "./dist/pipe.umd.js",
7 | "main": "./dist/pipe.js",
8 | "types": "./types/pipe.d.ts",
9 | "unpkg": "./dist/pipe.umd.js",
10 | "module": "./dist/pipe.esm.js",
11 | "jsdelivr": "./dist/pipe.umd.js",
12 | "umd:main": "./dist/pipe.umd.js",
13 | "exports": {
14 | ".": [
15 | {
16 | "import": "./dist/pipe.mjs",
17 | "require": "./dist/pipe.js",
18 | "default": "./dist/pipe.js"
19 | },
20 | "./dist/pipe.js"
21 | ]
22 | },
23 | "files": [
24 | "dist/",
25 | "types/"
26 | ],
27 | "keywords": [
28 | "pipe",
29 | "compose",
30 | "composition",
31 | "flow",
32 | "pipeline",
33 | "fp",
34 | "functional programming",
35 | "chain",
36 | "function",
37 | "functional",
38 | "serial"
39 | ],
40 | "scripts": {
41 | "test": "pnpm run test:code-style && pnpm run test:unit",
42 | "test:transpile": "tsc --project ./tsconfig.test.json",
43 | "test:unit": "pnpm run test:transpile && ava",
44 | "test:code-style": "prettier --check \"./{src,test}/**/*.ts\"",
45 | "build": "pnpm run build:transpile && pnpm run build:bundle",
46 | "build:transpile": "tsc --project ./tsconfig.build.json",
47 | "build:bundle": "rollup --config rollup.config.js",
48 | "prepublishOnly": "pnpm run test && pnpm run build"
49 | },
50 | "repository": {
51 | "type": "git",
52 | "url": "git+https://github.com/VitorLuizC/bitty.git",
53 | "directory": "packages/pipe"
54 | },
55 | "author": {
56 | "url": "https://vitorluizc.github.io/",
57 | "name": "Vitor Luiz Cavalcanti",
58 | "email": "vitorluizc@outlook.com"
59 | },
60 | "bugs": {
61 | "url": "https://github.com/VitorLuizC/bitty/issues"
62 | },
63 | "homepage": "https://github.com/VitorLuizC/bitty/tree/master/packages/pipe",
64 | "license": "MIT",
65 | "devDependencies": {
66 | "ava": "^4.0.1",
67 | "prettier": "^2.5.1",
68 | "rollup": "^2.63.0",
69 | "rollup-plugin-terser": "^7.0.2",
70 | "typescript": "^4.5.4"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/packages/pipe/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { terser } from 'rollup-plugin-terser';
2 |
3 | /**
4 | * Creates an output options object.
5 | * @param {import('rollup').OutputOptions} options
6 | * @returns {import('rollup').OutputOptions}
7 | */
8 | const Option = (options) => ({
9 | exports: 'default',
10 | sourcemap: true,
11 | ...options,
12 | });
13 |
14 | /**
15 | * An object with all configuration for `Rollup.js`.
16 | * @type {import('rollup').RollupOptions}
17 | */
18 | const options = {
19 | input: './src/pipe.js',
20 | output: [
21 | Option({
22 | file: './dist/pipe.js',
23 | format: 'commonjs',
24 | }),
25 | Option({
26 | file: './dist/pipe.esm.js',
27 | format: 'esm',
28 | }),
29 | Option({
30 | file: './dist/pipe.mjs',
31 | format: 'esm',
32 | }),
33 | Option({
34 | file: './dist/pipe.umd.js',
35 | name: 'pipe',
36 | format: 'umd',
37 | }),
38 | Option({
39 | file: './dist/pipe.umd.min.js',
40 | name: 'pipe',
41 | format: 'umd',
42 | plugins: [terser()],
43 | }),
44 | ],
45 | };
46 |
47 | export default options;
48 |
--------------------------------------------------------------------------------
/packages/pipe/src/pipe.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import pipe from './pipe.js';
3 |
4 | test('pipe is a function', (context) => {
5 | context.is(typeof pipe, 'function');
6 | });
7 |
8 | test('pipe compose functions in LTR direction', (context) => {
9 | const add = (x: number) => (y: number) => y + x;
10 | const subtract = (x: number) => (y: number) => y - x;
11 | const multiply = (x: number) => (y: number) => y * x;
12 | const divide = (x: number) => (y: number) => y / x;
13 |
14 | const calc = pipe(add(5), subtract(2), multiply(3), divide(2));
15 |
16 | context.is(calc(2), 7.5);
17 | context.not(calc(2), 6);
18 | });
19 |
20 | test("pipe's first function can handle more than one argument", (context) => {
21 | const getNames = (name: string, wordsToBeIgnored: string[] = []) =>
22 | name.split(' ').filter((word) => wordsToBeIgnored.indexOf(word) === -1);
23 |
24 | const formatToInitials = pipe(
25 | getNames,
26 | (names) => names.map((name) => name.charAt(0)),
27 | (initials) => initials.join('').toUpperCase(),
28 | );
29 |
30 | context.is(formatToInitials('Jairo de Almeida Machado', ['de']), 'JAM');
31 | });
32 |
--------------------------------------------------------------------------------
/packages/pipe/src/pipe.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Performs function composition in LTR (Left To Right) direction.
3 | *
4 | * Our `pipe` implementation supports N arguments. But you can use only 10 in
5 | * TypeScript, because it doesn't support **Variadic Kinds** and we explicitly
6 | * have to define the type of all the possible usages as method overloads.
7 | *
8 | * @example
9 | * const normalizeWhiteSpaces = text => name.replace(/\s+/g, ' ').trim();
10 | *
11 | * const getInitials = pipe(
12 | * normalizeWhiteSpaces,
13 | * name => name.split(' ').map(name => name.charAt(0)),
14 | * initials => initials.join('').toLocaleUpperCase()
15 | * );
16 | *
17 | * getInitials('Vitor Luiz Cavalcanti');
18 | * //=> "VLC"
19 | *
20 | * @param fn - An arity N function. Its result is the argument of next one.
21 | * @param fns - Functions of arity 1. Each one's result is next's argument.
22 | */
23 | // prettier-ignore
24 | export default function pipe(...fns: [(...xs: Args) => T0]): (...xs: Args) => T0;
25 | // prettier-ignore
26 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1]): (...xs: Args) => T1;
27 | // prettier-ignore
28 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1, (x: T1) => T2]): (...xs: Args) => T2;
29 | // prettier-ignore
30 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1, (x: T1) => T2, (x: T2) => T3]): (...xs: Args) => T3;
31 | // prettier-ignore
32 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1, (x: T1) => T2, (x: T2) => T3, (x: T3) => T4]): (...xs: Args) => T4;
33 | // prettier-ignore
34 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1, (x: T1) => T2, (x: T2) => T3, (x: T3) => T4, (x: T4) => T5]): (...xs: Args) => T5;
35 | // prettier-ignore
36 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1, (x: T1) => T2, (x: T2) => T3, (x: T3) => T4, (x: T4) => T5, (x: T5) => T6]): (...xs: Args) => T6;
37 | // prettier-ignore
38 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1, (x: T1) => T2, (x: T2) => T3, (x: T3) => T4, (x: T4) => T5, (x: T5) => T6, (x: T6) => T7]): (...xs: Args) => T7;
39 | // prettier-ignore
40 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1, (x: T1) => T2, (x: T2) => T3, (x: T3) => T4, (x: T4) => T5, (x: T5) => T6, (x: T6) => T7, (x: T7) => T8]): (...xs: Args) => T8;
41 | // prettier-ignore
42 | export default function pipe(...fns: [(...xs: Args) => T0, (x: T0) => T1, (x: T1) => T2, (x: T2) => T3, (x: T3) => T4, (x: T4) => T5, (x: T5) => T6, (x: T6) => T7, (x: T7) => T8, (x: T8) => T9]): (...xs: Args) => T9;
43 |
44 | /**
45 | * Performs function composition in LTR (Left To Right) direction.
46 | *
47 | * @example
48 | * const normalizeWhiteSpaces = text => name.replace(/\s+/g, ' ').trim();
49 | *
50 | * const getInitials = pipe(
51 | * normalizeWhiteSpaces,
52 | * name => name.split(' ').map(name => name.charAt(0)),
53 | * initials => initials.join('').toLocaleUpperCase()
54 | * );
55 | *
56 | * getInitials('Vitor Luiz Cavalcanti');
57 | * //=> "VLC"
58 | *
59 | * @param {Function} fn - An arity N function. Its result is the argument of next one.
60 | * @param {...Function[]} fns - Functions of arity 1. Each one's result is next's argument.
61 | * @returns {Function}
62 | */
63 | export default function pipe(fn: Function) {
64 | const fns = [].slice.call(arguments, 1) as Function[];
65 | return function () {
66 | return fns.reduce((x, fn) => fn(x), fn.apply(null, arguments));
67 | };
68 | }
69 |
--------------------------------------------------------------------------------
/packages/pipe/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | // Type declaration settings
5 | "declarationDir": "./types",
6 |
7 | // ECMAScript version settings
8 | "lib": ["ES5"]
9 | },
10 | "include": ["./src/**/*.ts"],
11 | "exclude": ["./src/**/*.spec.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/pipe/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/pipe/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "CommonJS"
5 | },
6 | "exclude": []
7 | }
8 |
--------------------------------------------------------------------------------
/packages/predicate/.gitignore:
--------------------------------------------------------------------------------
1 | # Bundled modules and their source-maps.
2 | dist/
3 |
4 | # Generated type declarations.
5 | types/
6 |
7 | # Transpiled modules and their source-maps.
8 | src/**/*.js
9 | src/**/*.js.map
10 |
--------------------------------------------------------------------------------
/packages/predicate/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('../../.prettierrc.js');
2 |
--------------------------------------------------------------------------------
/packages/predicate/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vitor Luiz Cavalcanti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/predicate/README.md:
--------------------------------------------------------------------------------
1 | # `@bitty/predicate`
2 |
3 | [](https://bundlephobia.com/result?p=@bitty/predicate)
4 | [](https://bundlephobia.com/result?p=@bitty/predicate)
5 |
6 | `Predicate` and `Refinement` types for TypeScript.
7 |
8 | - 🏷 Safe:
9 | - JSDocs and type declarations for IDEs and editor's autocomplete/intellisense.
10 | - Made with TypeScript as strict as possible.
11 | - Unit tests with AVA.
12 |
13 | ## Installation
14 |
15 | This library is published in the NPM registry and can be installed using any compatible package manager.
16 |
17 | ```sh
18 | npm install @bitty/predicate --save
19 |
20 | # For Yarn, use the command below.
21 | yarn add @bitty/predicate
22 | ```
23 |
24 | ## Getting Stated
25 |
26 | It exports `Predicate` and `Refinement` types.
27 |
28 | - `Predicate` is a function that receives a value and returns a boolean.
29 |
30 | ```ts
31 | import type { Predicate } from '@bitty/predicate';
32 |
33 | function checkAll(predicates: Predicate[]): Predicate {
34 | return (value) => predicates.every((predicate) => predicate(value));
35 | }
36 | ```
37 |
38 | - `Refinement` is similar to `Predicate`, but uses [TypeScript `is` type guard](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards).
39 |
40 | ```ts
41 | import { Refinement } from '@bitty/predicate';
42 |
43 | const isNumber: Refinement = (value) =>
44 | Number.isFinite(value);
45 | //=> Was typed as `(value: unknown) => value is number`.
46 |
47 | const value: number | string = Math.random() > 0.5 ? 100 : 'A text.';
48 |
49 | if (isNumber(value)) {
50 | console.log(value.toFixed(2));
51 | //=> Okay, because type of `value` was refined to `number`.
52 | }
53 | console.log(value.toFixed(2));
54 | //=> Property 'toFixed' does not exist on type 'string | number'.
55 | // Property 'toFixed' does not exist on type 'string'.
56 | ```
57 |
58 | ## License
59 |
60 | Released under [MIT License](./LICENSE).
61 |
--------------------------------------------------------------------------------
/packages/predicate/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bitty/predicate",
3 | "version": "0.2.0",
4 | "description": "Predicate helper functions and types for TypeScript.",
5 | "sideEffects": false,
6 | "cdn": "./dist/main.umd.min.js",
7 | "main": "./dist/main.js",
8 | "types": "./types/main.d.ts",
9 | "unpkg": "./dist/main.umd.min.js",
10 | "module": "./dist/main.esm.js",
11 | "jsdelivr": "./dist/main.umd.min.js",
12 | "umd:main": "./dist/main.umd.js",
13 | "exports": {
14 | ".": [
15 | {
16 | "import": "./dist/main.mjs",
17 | "require": "./dist/main.js",
18 | "default": "./dist/main.js"
19 | },
20 | "./dist/main.js"
21 | ]
22 | },
23 | "files": [
24 | "dist/",
25 | "types/"
26 | ],
27 | "keywords": [
28 | "predicate",
29 | "type",
30 | "types",
31 | "type-guard",
32 | "type-predicate",
33 | "type-helper",
34 | "typescript",
35 | "typescript-types",
36 | "fp",
37 | "functional programming",
38 | "function",
39 | "functional"
40 | ],
41 | "scripts": {
42 | "test": "pnpm run test:code-style && pnpm run test:unit",
43 | "test:transpile": "tsc --project ./tsconfig.test.json",
44 | "test:unit": "pnpm run test:transpile && ava",
45 | "test:code-style": "prettier --check \"./src/**/*.ts\"",
46 | "build": "pnpm run build:transpile && pnpm run build:bundle",
47 | "build:transpile": "tsc --project ./tsconfig.build.json",
48 | "build:bundle": "rollup --config rollup.config.js",
49 | "prepublishOnly": "pnpm run test && pnpm run build"
50 | },
51 | "repository": {
52 | "type": "git",
53 | "url": "git+https://github.com/VitorLuizC/bitty.git",
54 | "directory": "packages/predicate"
55 | },
56 | "author": {
57 | "url": "https://vitorluizc.github.io/",
58 | "name": "Vitor Luiz Cavalcanti",
59 | "email": "vitorluizc@outlook.com"
60 | },
61 | "bugs": {
62 | "url": "https://github.com/VitorLuizC/bitty/issues"
63 | },
64 | "homepage": "https://github.com/VitorLuizC/bitty/tree/master/packages/predicate",
65 | "license": "MIT",
66 | "devDependencies": {
67 | "ava": "^4.0.1",
68 | "prettier": "^2.5.1",
69 | "rollup": "^2.63.0",
70 | "rollup-plugin-terser": "^7.0.2",
71 | "typescript": "^4.5.4"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/packages/predicate/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { terser } from 'rollup-plugin-terser';
2 |
3 | /**
4 | * Creates an output options object.
5 | * @param {import('rollup').OutputOptions} options
6 | * @returns {import('rollup').OutputOptions}
7 | */
8 | const Option = (options) => ({
9 | exports: 'named',
10 | sourcemap: true,
11 | ...options,
12 | });
13 |
14 | /**
15 | * An object with all configuration for `Rollup.js`.
16 | * @type {import('rollup').RollupOptions}
17 | */
18 | const options = {
19 | input: './src/main.js',
20 | output: [
21 | Option({
22 | file: './dist/main.js',
23 | format: 'commonjs',
24 | }),
25 | Option({
26 | file: './dist/main.esm.js',
27 | format: 'esm',
28 | }),
29 | Option({
30 | file: './dist/main.mjs',
31 | format: 'esm',
32 | }),
33 | Option({
34 | file: './dist/main.umd.js',
35 | name: 'Predicate',
36 | format: 'umd',
37 | }),
38 | Option({
39 | file: './dist/main.umd.min.js',
40 | name: 'Predicate',
41 | format: 'umd',
42 | plugins: [terser()],
43 | }),
44 | ],
45 | };
46 |
47 | export default options;
48 |
--------------------------------------------------------------------------------
/packages/predicate/src/main.spec.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import type { Predicate, Refinement } from './main';
3 |
4 | test('Predicate is a function that receives a value and returns boolean', (context) => {
5 | type Assert = T2 extends T ? true : false;
6 |
7 | const V1: Assert boolean> = true;
8 | const V2: Assert, (value: string) => boolean> = true;
9 |
10 | context.true(V1);
11 | context.true(V2);
12 | });
13 |
14 | test('Refinement is a Predicate that uses `is` type guard', (context) => {
15 | type Assert = T2 extends T ? true : false;
16 |
17 | const V1: Assert, Refinement> = true;
18 | const V2: Assert<
19 | Refinement,
20 | (value: string) => value is 'Okay'
21 | > = true;
22 | const V3: Assert<
23 | Refinement,
24 | (value: 0 | 1 | 2) => value is 0
25 | > = false;
26 |
27 | context.true(V1);
28 | context.true(V2);
29 | context.false(V3);
30 | });
31 |
--------------------------------------------------------------------------------
/packages/predicate/src/main.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * A function that check if value (`T`) matches some predicate.
3 | */
4 | export type Predicate = (value: T) => boolean;
5 |
6 | /**
7 | * A function that check if value (`T`) is of type `T2`.
8 | */
9 | export type Refinement = (value: T) => value is T2;
10 |
--------------------------------------------------------------------------------
/packages/predicate/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.build.json",
3 | "compilerOptions": {
4 | // Type declaration settings
5 | "declarationDir": "./types",
6 |
7 | // ECMAScript version settings
8 | "lib": ["ES5"]
9 | },
10 | "include": ["./src/**/*.ts"],
11 | "exclude": ["./src/**/*.spec.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/predicate/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "target": "ESNext"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/packages/predicate/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "CommonJS"
5 | },
6 | "exclude": []
7 | }
8 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.3
2 |
3 | importers:
4 |
5 | .:
6 | specifiers:
7 | pnpm: ^6.25.1
8 | devDependencies:
9 | pnpm: 6.25.1
10 |
11 | packages/animate:
12 | specifiers:
13 | ava: ^4.0.1
14 | prettier: ^2.5.1
15 | rollup: ^2.63.0
16 | rollup-plugin-terser: ^7.0.2
17 | typescript: ^4.5.4
18 | devDependencies:
19 | ava: 4.0.1
20 | prettier: 2.5.1
21 | rollup: 2.63.0
22 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
23 | typescript: 4.5.4
24 |
25 | packages/create-request:
26 | specifiers:
27 | prettier: ^2.5.1
28 | rollup: ^2.63.0
29 | rollup-plugin-terser: ^7.0.2
30 | typescript: ^4.5.4
31 | devDependencies:
32 | prettier: 2.5.1
33 | rollup: 2.63.0
34 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
35 | typescript: 4.5.4
36 |
37 | packages/deferred:
38 | specifiers:
39 | ava: ^4.0.1
40 | prettier: ^2.5.1
41 | rollup: ^2.63.0
42 | rollup-plugin-terser: ^7.0.2
43 | typescript: ^4.5.4
44 | devDependencies:
45 | ava: 4.0.1
46 | prettier: 2.5.1
47 | rollup: 2.63.0
48 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
49 | typescript: 4.5.4
50 |
51 | packages/either:
52 | specifiers:
53 | '@bitty/falsy': workspace:*
54 | '@bitty/nullish': workspace:*
55 | '@bitty/predicate': workspace:*
56 | '@rollup/plugin-node-resolve': ^13.1.3
57 | ava: ^4.0.1
58 | jwt-decode: ^3.1.2
59 | prettier: ^2.5.1
60 | rollup: ^2.63.0
61 | rollup-plugin-terser: ^7.0.2
62 | typescript: ^4.5.4
63 | dependencies:
64 | '@bitty/falsy': link:../falsy
65 | '@bitty/nullish': link:../nullish
66 | '@bitty/predicate': link:../predicate
67 | devDependencies:
68 | '@rollup/plugin-node-resolve': 13.1.3_rollup@2.63.0
69 | ava: 4.0.1
70 | jwt-decode: 3.1.2
71 | prettier: 2.5.1
72 | rollup: 2.63.0
73 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
74 | typescript: 4.5.4
75 |
76 | packages/event-emitter:
77 | specifiers:
78 | ava: ^4.0.1
79 | prettier: ^2.5.1
80 | rollup: ^2.63.0
81 | rollup-plugin-terser: ^7.0.2
82 | typescript: ^4.5.4
83 | devDependencies:
84 | ava: 4.0.1
85 | prettier: 2.5.1
86 | rollup: 2.63.0
87 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
88 | typescript: 4.5.4
89 |
90 | packages/falsy:
91 | specifiers:
92 | ava: ^4.0.1
93 | prettier: ^2.5.1
94 | rollup: ^2.63.0
95 | rollup-plugin-terser: ^7.0.2
96 | typescript: ^4.5.4
97 | devDependencies:
98 | ava: 4.0.1
99 | prettier: 2.5.1
100 | rollup: 2.63.0
101 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
102 | typescript: 4.5.4
103 |
104 | packages/format-date:
105 | specifiers:
106 | ava: ^4.0.1
107 | prettier: ^2.5.1
108 | rollup: ^2.63.0
109 | rollup-plugin-terser: ^7.0.2
110 | typescript: ^4.5.4
111 | devDependencies:
112 | ava: 4.0.1
113 | prettier: 2.5.1
114 | rollup: 2.63.0
115 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
116 | typescript: 4.5.4
117 |
118 | packages/get:
119 | specifiers:
120 | ava: ^4.0.1
121 | prettier: ^2.5.1
122 | rollup: ^2.63.0
123 | rollup-plugin-terser: ^7.0.2
124 | typescript: ^4.5.4
125 | devDependencies:
126 | ava: 4.0.1
127 | prettier: 2.5.1
128 | rollup: 2.63.0
129 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
130 | typescript: 4.5.4
131 |
132 | packages/insist:
133 | specifiers:
134 | ava: ^4.0.1
135 | prettier: ^2.5.1
136 | rollup: ^2.63.0
137 | rollup-plugin-terser: ^7.0.2
138 | typescript: ^4.5.4
139 | devDependencies:
140 | ava: 4.0.1
141 | prettier: 2.5.1
142 | rollup: 2.63.0
143 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
144 | typescript: 4.5.4
145 |
146 | packages/json:
147 | specifiers:
148 | ava: ^4.0.1
149 | prettier: ^2.5.1
150 | rollup: ^2.63.0
151 | rollup-plugin-terser: ^7.0.2
152 | typescript: ^4.5.4
153 | devDependencies:
154 | ava: 4.0.1
155 | prettier: 2.5.1
156 | rollup: 2.63.0
157 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
158 | typescript: 4.5.4
159 |
160 | packages/maybe:
161 | specifiers:
162 | '@bitty/falsy': workspace:*
163 | '@bitty/nullish': workspace:*
164 | '@bitty/predicate': workspace:*
165 | '@rollup/plugin-node-resolve': ^13.1.3
166 | rollup: ^2.63.0
167 | rollup-plugin-terser: ^7.0.2
168 | typescript: ^4.5.4
169 | dependencies:
170 | '@bitty/falsy': link:../falsy
171 | '@bitty/nullish': link:../nullish
172 | '@bitty/predicate': link:../predicate
173 | devDependencies:
174 | '@rollup/plugin-node-resolve': 13.1.3_rollup@2.63.0
175 | rollup: 2.63.0
176 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
177 | typescript: 4.5.4
178 |
179 | packages/nullish:
180 | specifiers:
181 | ava: ^4.0.1
182 | prettier: ^2.5.1
183 | rollup: ^2.63.0
184 | rollup-plugin-terser: ^7.0.2
185 | typescript: ^4.5.4
186 | devDependencies:
187 | ava: 4.0.1
188 | prettier: 2.5.1
189 | rollup: 2.63.0
190 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
191 | typescript: 4.5.4
192 |
193 | packages/pipe:
194 | specifiers:
195 | ava: ^4.0.1
196 | prettier: ^2.5.1
197 | rollup: ^2.63.0
198 | rollup-plugin-terser: ^7.0.2
199 | typescript: ^4.5.4
200 | devDependencies:
201 | ava: 4.0.1
202 | prettier: 2.5.1
203 | rollup: 2.63.0
204 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
205 | typescript: 4.5.4
206 |
207 | packages/predicate:
208 | specifiers:
209 | ava: ^4.0.1
210 | prettier: ^2.5.1
211 | rollup: ^2.63.0
212 | rollup-plugin-terser: ^7.0.2
213 | typescript: ^4.5.4
214 | devDependencies:
215 | ava: 4.0.1
216 | prettier: 2.5.1
217 | rollup: 2.63.0
218 | rollup-plugin-terser: 7.0.2_rollup@2.63.0
219 | typescript: 4.5.4
220 |
221 | packages:
222 |
223 | /@babel/code-frame/7.16.7:
224 | resolution: {integrity: sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==}
225 | engines: {node: '>=6.9.0'}
226 | dependencies:
227 | '@babel/highlight': 7.16.7
228 | dev: true
229 |
230 | /@babel/helper-validator-identifier/7.16.7:
231 | resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==}
232 | engines: {node: '>=6.9.0'}
233 | dev: true
234 |
235 | /@babel/highlight/7.16.7:
236 | resolution: {integrity: sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw==}
237 | engines: {node: '>=6.9.0'}
238 | dependencies:
239 | '@babel/helper-validator-identifier': 7.16.7
240 | chalk: 2.4.2
241 | js-tokens: 4.0.0
242 | dev: true
243 |
244 | /@nodelib/fs.scandir/2.1.5:
245 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
246 | engines: {node: '>= 8'}
247 | dependencies:
248 | '@nodelib/fs.stat': 2.0.5
249 | run-parallel: 1.2.0
250 | dev: true
251 |
252 | /@nodelib/fs.stat/2.0.5:
253 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
254 | engines: {node: '>= 8'}
255 | dev: true
256 |
257 | /@nodelib/fs.walk/1.2.8:
258 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
259 | engines: {node: '>= 8'}
260 | dependencies:
261 | '@nodelib/fs.scandir': 2.1.5
262 | fastq: 1.13.0
263 | dev: true
264 |
265 | /@rollup/plugin-node-resolve/13.1.3_rollup@2.63.0:
266 | resolution: {integrity: sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ==}
267 | engines: {node: '>= 10.0.0'}
268 | peerDependencies:
269 | rollup: ^2.42.0
270 | dependencies:
271 | '@rollup/pluginutils': 3.1.0_rollup@2.63.0
272 | '@types/resolve': 1.17.1
273 | builtin-modules: 3.2.0
274 | deepmerge: 4.2.2
275 | is-module: 1.0.0
276 | resolve: 1.21.0
277 | rollup: 2.63.0
278 | dev: true
279 |
280 | /@rollup/pluginutils/3.1.0_rollup@2.63.0:
281 | resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
282 | engines: {node: '>= 8.0.0'}
283 | peerDependencies:
284 | rollup: ^1.20.0||^2.0.0
285 | dependencies:
286 | '@types/estree': 0.0.39
287 | estree-walker: 1.0.1
288 | picomatch: 2.3.1
289 | rollup: 2.63.0
290 | dev: true
291 |
292 | /@types/estree/0.0.39:
293 | resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==}
294 | dev: true
295 |
296 | /@types/node/17.0.8:
297 | resolution: {integrity: sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==}
298 | dev: true
299 |
300 | /@types/resolve/1.17.1:
301 | resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
302 | dependencies:
303 | '@types/node': 17.0.8
304 | dev: true
305 |
306 | /acorn-walk/8.2.0:
307 | resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
308 | engines: {node: '>=0.4.0'}
309 | dev: true
310 |
311 | /acorn/8.7.0:
312 | resolution: {integrity: sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==}
313 | engines: {node: '>=0.4.0'}
314 | hasBin: true
315 | dev: true
316 |
317 | /aggregate-error/3.1.0:
318 | resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
319 | engines: {node: '>=8'}
320 | dependencies:
321 | clean-stack: 2.2.0
322 | indent-string: 4.0.0
323 | dev: true
324 |
325 | /aggregate-error/4.0.0:
326 | resolution: {integrity: sha512-8DGp7zUt1E9k0NE2q4jlXHk+V3ORErmwolEdRz9iV+LKJ40WhMHh92cxAvhqV2I+zEn/gotIoqoMs0NjF3xofg==}
327 | engines: {node: '>=12'}
328 | dependencies:
329 | clean-stack: 4.1.0
330 | indent-string: 5.0.0
331 | dev: true
332 |
333 | /ansi-regex/5.0.1:
334 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
335 | engines: {node: '>=8'}
336 | dev: true
337 |
338 | /ansi-regex/6.0.1:
339 | resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
340 | engines: {node: '>=12'}
341 | dev: true
342 |
343 | /ansi-styles/3.2.1:
344 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
345 | engines: {node: '>=4'}
346 | dependencies:
347 | color-convert: 1.9.3
348 | dev: true
349 |
350 | /ansi-styles/4.3.0:
351 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
352 | engines: {node: '>=8'}
353 | dependencies:
354 | color-convert: 2.0.1
355 | dev: true
356 |
357 | /ansi-styles/6.1.0:
358 | resolution: {integrity: sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==}
359 | engines: {node: '>=12'}
360 | dev: true
361 |
362 | /anymatch/3.1.2:
363 | resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
364 | engines: {node: '>= 8'}
365 | dependencies:
366 | normalize-path: 3.0.0
367 | picomatch: 2.3.1
368 | dev: true
369 |
370 | /argparse/1.0.10:
371 | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
372 | dependencies:
373 | sprintf-js: 1.0.3
374 | dev: true
375 |
376 | /array-find-index/1.0.2:
377 | resolution: {integrity: sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=}
378 | engines: {node: '>=0.10.0'}
379 | dev: true
380 |
381 | /array-union/2.1.0:
382 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
383 | engines: {node: '>=8'}
384 | dev: true
385 |
386 | /array-union/3.0.1:
387 | resolution: {integrity: sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==}
388 | engines: {node: '>=12'}
389 | dev: true
390 |
391 | /arrgv/1.0.2:
392 | resolution: {integrity: sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==}
393 | engines: {node: '>=8.0.0'}
394 | dev: true
395 |
396 | /arrify/2.0.1:
397 | resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==}
398 | engines: {node: '>=8'}
399 | dev: true
400 |
401 | /arrify/3.0.0:
402 | resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==}
403 | engines: {node: '>=12'}
404 | dev: true
405 |
406 | /ava/4.0.1:
407 | resolution: {integrity: sha512-+12A/JDWyShBCZAKISEEPyM2dwkUrrAfPILqXi4LI4Aa58d92PzjY829hmuoSeACPNqrn2Wlbnja8c/n7bKV6Q==}
408 | engines: {node: '>=12.22 <13 || >=14.17 <15 || >=16.4 <17 || >=17'}
409 | hasBin: true
410 | peerDependencies:
411 | '@ava/typescript': '*'
412 | peerDependenciesMeta:
413 | '@ava/typescript':
414 | optional: true
415 | dependencies:
416 | acorn: 8.7.0
417 | acorn-walk: 8.2.0
418 | ansi-styles: 6.1.0
419 | arrgv: 1.0.2
420 | arrify: 3.0.0
421 | callsites: 4.0.0
422 | cbor: 8.1.0
423 | chalk: 5.0.0
424 | chokidar: 3.5.2
425 | chunkd: 2.0.1
426 | ci-info: 3.3.0
427 | ci-parallel-vars: 1.0.1
428 | clean-yaml-object: 0.1.0
429 | cli-truncate: 3.1.0
430 | code-excerpt: 3.0.0
431 | common-path-prefix: 3.0.0
432 | concordance: 5.0.4
433 | currently-unhandled: 0.4.1
434 | debug: 4.3.3
435 | del: 6.0.0
436 | emittery: 0.10.0
437 | figures: 4.0.0
438 | globby: 12.0.2
439 | ignore-by-default: 2.0.0
440 | indent-string: 5.0.0
441 | is-error: 2.2.2
442 | is-plain-object: 5.0.0
443 | is-promise: 4.0.0
444 | matcher: 5.0.0
445 | mem: 9.0.1
446 | ms: 2.1.3
447 | p-event: 5.0.1
448 | p-map: 5.3.0
449 | picomatch: 2.3.1
450 | pkg-conf: 4.0.0
451 | plur: 5.1.0
452 | pretty-ms: 7.0.1
453 | resolve-cwd: 3.0.0
454 | slash: 3.0.0
455 | stack-utils: 2.0.5
456 | strip-ansi: 7.0.1
457 | supertap: 2.0.0
458 | temp-dir: 2.0.0
459 | write-file-atomic: 3.0.3
460 | yargs: 17.3.1
461 | transitivePeerDependencies:
462 | - supports-color
463 | dev: true
464 |
465 | /balanced-match/1.0.2:
466 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
467 | dev: true
468 |
469 | /binary-extensions/2.2.0:
470 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
471 | engines: {node: '>=8'}
472 | dev: true
473 |
474 | /blueimp-md5/2.19.0:
475 | resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==}
476 | dev: true
477 |
478 | /brace-expansion/1.1.11:
479 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
480 | dependencies:
481 | balanced-match: 1.0.2
482 | concat-map: 0.0.1
483 | dev: true
484 |
485 | /braces/3.0.2:
486 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
487 | engines: {node: '>=8'}
488 | dependencies:
489 | fill-range: 7.0.1
490 | dev: true
491 |
492 | /buffer-from/1.1.2:
493 | resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
494 | dev: true
495 |
496 | /builtin-modules/3.2.0:
497 | resolution: {integrity: sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==}
498 | engines: {node: '>=6'}
499 | dev: true
500 |
501 | /callsites/4.0.0:
502 | resolution: {integrity: sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ==}
503 | engines: {node: '>=12.20'}
504 | dev: true
505 |
506 | /cbor/8.1.0:
507 | resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==}
508 | engines: {node: '>=12.19'}
509 | dependencies:
510 | nofilter: 3.1.0
511 | dev: true
512 |
513 | /chalk/2.4.2:
514 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
515 | engines: {node: '>=4'}
516 | dependencies:
517 | ansi-styles: 3.2.1
518 | escape-string-regexp: 1.0.5
519 | supports-color: 5.5.0
520 | dev: true
521 |
522 | /chalk/5.0.0:
523 | resolution: {integrity: sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ==}
524 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
525 | dev: true
526 |
527 | /chokidar/3.5.2:
528 | resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==}
529 | engines: {node: '>= 8.10.0'}
530 | dependencies:
531 | anymatch: 3.1.2
532 | braces: 3.0.2
533 | glob-parent: 5.1.2
534 | is-binary-path: 2.1.0
535 | is-glob: 4.0.3
536 | normalize-path: 3.0.0
537 | readdirp: 3.6.0
538 | optionalDependencies:
539 | fsevents: 2.3.2
540 | dev: true
541 |
542 | /chunkd/2.0.1:
543 | resolution: {integrity: sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==}
544 | dev: true
545 |
546 | /ci-info/3.3.0:
547 | resolution: {integrity: sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==}
548 | dev: true
549 |
550 | /ci-parallel-vars/1.0.1:
551 | resolution: {integrity: sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==}
552 | dev: true
553 |
554 | /clean-stack/2.2.0:
555 | resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
556 | engines: {node: '>=6'}
557 | dev: true
558 |
559 | /clean-stack/4.1.0:
560 | resolution: {integrity: sha512-dxXQYI7mfQVcaF12s6sjNFoZ6ZPDQuBBLp3QJ5156k9EvUFClUoZ11fo8HnLQO241DDVntHEug8MOuFO5PSfRg==}
561 | engines: {node: '>=12'}
562 | dependencies:
563 | escape-string-regexp: 5.0.0
564 | dev: true
565 |
566 | /clean-yaml-object/0.1.0:
567 | resolution: {integrity: sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=}
568 | engines: {node: '>=0.10.0'}
569 | dev: true
570 |
571 | /cli-truncate/3.1.0:
572 | resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==}
573 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
574 | dependencies:
575 | slice-ansi: 5.0.0
576 | string-width: 5.1.0
577 | dev: true
578 |
579 | /cliui/7.0.4:
580 | resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
581 | dependencies:
582 | string-width: 4.2.3
583 | strip-ansi: 6.0.1
584 | wrap-ansi: 7.0.0
585 | dev: true
586 |
587 | /code-excerpt/3.0.0:
588 | resolution: {integrity: sha512-VHNTVhd7KsLGOqfX3SyeO8RyYPMp1GJOg194VITk04WMYCv4plV68YWe6TJZxd9MhobjtpMRnVky01gqZsalaw==}
589 | engines: {node: '>=10'}
590 | dependencies:
591 | convert-to-spaces: 1.0.2
592 | dev: true
593 |
594 | /color-convert/1.9.3:
595 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
596 | dependencies:
597 | color-name: 1.1.3
598 | dev: true
599 |
600 | /color-convert/2.0.1:
601 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
602 | engines: {node: '>=7.0.0'}
603 | dependencies:
604 | color-name: 1.1.4
605 | dev: true
606 |
607 | /color-name/1.1.3:
608 | resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=}
609 | dev: true
610 |
611 | /color-name/1.1.4:
612 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
613 | dev: true
614 |
615 | /commander/2.20.3:
616 | resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
617 | dev: true
618 |
619 | /common-path-prefix/3.0.0:
620 | resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==}
621 | dev: true
622 |
623 | /concat-map/0.0.1:
624 | resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
625 | dev: true
626 |
627 | /concordance/5.0.4:
628 | resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==}
629 | engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'}
630 | dependencies:
631 | date-time: 3.1.0
632 | esutils: 2.0.3
633 | fast-diff: 1.2.0
634 | js-string-escape: 1.0.1
635 | lodash: 4.17.21
636 | md5-hex: 3.0.1
637 | semver: 7.3.5
638 | well-known-symbols: 2.0.0
639 | dev: true
640 |
641 | /convert-to-spaces/1.0.2:
642 | resolution: {integrity: sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU=}
643 | engines: {node: '>= 4'}
644 | dev: true
645 |
646 | /currently-unhandled/0.4.1:
647 | resolution: {integrity: sha1-mI3zP+qxke95mmE2nddsF635V+o=}
648 | engines: {node: '>=0.10.0'}
649 | dependencies:
650 | array-find-index: 1.0.2
651 | dev: true
652 |
653 | /date-time/3.1.0:
654 | resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==}
655 | engines: {node: '>=6'}
656 | dependencies:
657 | time-zone: 1.0.0
658 | dev: true
659 |
660 | /debug/4.3.3:
661 | resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==}
662 | engines: {node: '>=6.0'}
663 | peerDependencies:
664 | supports-color: '*'
665 | peerDependenciesMeta:
666 | supports-color:
667 | optional: true
668 | dependencies:
669 | ms: 2.1.2
670 | dev: true
671 |
672 | /deepmerge/4.2.2:
673 | resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==}
674 | engines: {node: '>=0.10.0'}
675 | dev: true
676 |
677 | /del/6.0.0:
678 | resolution: {integrity: sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==}
679 | engines: {node: '>=10'}
680 | dependencies:
681 | globby: 11.1.0
682 | graceful-fs: 4.2.9
683 | is-glob: 4.0.3
684 | is-path-cwd: 2.2.0
685 | is-path-inside: 3.0.3
686 | p-map: 4.0.0
687 | rimraf: 3.0.2
688 | slash: 3.0.0
689 | dev: true
690 |
691 | /dir-glob/3.0.1:
692 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
693 | engines: {node: '>=8'}
694 | dependencies:
695 | path-type: 4.0.0
696 | dev: true
697 |
698 | /eastasianwidth/0.2.0:
699 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
700 | dev: true
701 |
702 | /emittery/0.10.0:
703 | resolution: {integrity: sha512-AGvFfs+d0JKCJQ4o01ASQLGPmSCxgfU9RFXvzPvZdjKK8oscynksuJhWrSTSw7j7Ep/sZct5b5ZhYCi8S/t0HQ==}
704 | engines: {node: '>=12'}
705 | dev: true
706 |
707 | /emoji-regex/8.0.0:
708 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
709 | dev: true
710 |
711 | /emoji-regex/9.2.2:
712 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
713 | dev: true
714 |
715 | /escalade/3.1.1:
716 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
717 | engines: {node: '>=6'}
718 | dev: true
719 |
720 | /escape-string-regexp/1.0.5:
721 | resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=}
722 | engines: {node: '>=0.8.0'}
723 | dev: true
724 |
725 | /escape-string-regexp/2.0.0:
726 | resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
727 | engines: {node: '>=8'}
728 | dev: true
729 |
730 | /escape-string-regexp/5.0.0:
731 | resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
732 | engines: {node: '>=12'}
733 | dev: true
734 |
735 | /esprima/4.0.1:
736 | resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
737 | engines: {node: '>=4'}
738 | hasBin: true
739 | dev: true
740 |
741 | /estree-walker/1.0.1:
742 | resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==}
743 | dev: true
744 |
745 | /esutils/2.0.3:
746 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
747 | engines: {node: '>=0.10.0'}
748 | dev: true
749 |
750 | /fast-diff/1.2.0:
751 | resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==}
752 | dev: true
753 |
754 | /fast-glob/3.2.10:
755 | resolution: {integrity: sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A==}
756 | engines: {node: '>=8.6.0'}
757 | dependencies:
758 | '@nodelib/fs.stat': 2.0.5
759 | '@nodelib/fs.walk': 1.2.8
760 | glob-parent: 5.1.2
761 | merge2: 1.4.1
762 | micromatch: 4.0.4
763 | dev: true
764 |
765 | /fastq/1.13.0:
766 | resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
767 | dependencies:
768 | reusify: 1.0.4
769 | dev: true
770 |
771 | /figures/4.0.0:
772 | resolution: {integrity: sha512-VnYcWq6H6F0qDN0QnorznBr0abEovifzUokmnezpKZBUbDmbLAt7LMryOp1TKFVxLxyNYkxEkCEADZR58U9oSw==}
773 | engines: {node: '>=12'}
774 | dependencies:
775 | escape-string-regexp: 5.0.0
776 | is-unicode-supported: 1.1.0
777 | dev: true
778 |
779 | /fill-range/7.0.1:
780 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
781 | engines: {node: '>=8'}
782 | dependencies:
783 | to-regex-range: 5.0.1
784 | dev: true
785 |
786 | /find-up/6.2.0:
787 | resolution: {integrity: sha512-yWHzMzXCaFoABSnFTCPKNFlYoq4mSga9QLRRKOCLSJ33hSkzROB14ITbAWW0QDQDyuzsPQ33S1DsOWQb/oW1yA==}
788 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
789 | dependencies:
790 | locate-path: 7.0.0
791 | path-exists: 5.0.0
792 | dev: true
793 |
794 | /fs.realpath/1.0.0:
795 | resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=}
796 | dev: true
797 |
798 | /fsevents/2.3.2:
799 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
800 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
801 | os: [darwin]
802 | requiresBuild: true
803 | dev: true
804 | optional: true
805 |
806 | /function-bind/1.1.1:
807 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
808 | dev: true
809 |
810 | /get-caller-file/2.0.5:
811 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
812 | engines: {node: 6.* || 8.* || >= 10.*}
813 | dev: true
814 |
815 | /glob-parent/5.1.2:
816 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
817 | engines: {node: '>= 6'}
818 | dependencies:
819 | is-glob: 4.0.3
820 | dev: true
821 |
822 | /glob/7.2.0:
823 | resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
824 | dependencies:
825 | fs.realpath: 1.0.0
826 | inflight: 1.0.6
827 | inherits: 2.0.4
828 | minimatch: 3.0.4
829 | once: 1.4.0
830 | path-is-absolute: 1.0.1
831 | dev: true
832 |
833 | /globby/11.1.0:
834 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
835 | engines: {node: '>=10'}
836 | dependencies:
837 | array-union: 2.1.0
838 | dir-glob: 3.0.1
839 | fast-glob: 3.2.10
840 | ignore: 5.2.0
841 | merge2: 1.4.1
842 | slash: 3.0.0
843 | dev: true
844 |
845 | /globby/12.0.2:
846 | resolution: {integrity: sha512-lAsmb/5Lww4r7MM9nCCliDZVIKbZTavrsunAsHLr9oHthrZP1qi7/gAnHOsUs9bLvEt2vKVJhHmxuL7QbDuPdQ==}
847 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
848 | dependencies:
849 | array-union: 3.0.1
850 | dir-glob: 3.0.1
851 | fast-glob: 3.2.10
852 | ignore: 5.2.0
853 | merge2: 1.4.1
854 | slash: 4.0.0
855 | dev: true
856 |
857 | /graceful-fs/4.2.9:
858 | resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==}
859 | dev: true
860 |
861 | /has-flag/3.0.0:
862 | resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=}
863 | engines: {node: '>=4'}
864 | dev: true
865 |
866 | /has-flag/4.0.0:
867 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
868 | engines: {node: '>=8'}
869 | dev: true
870 |
871 | /has/1.0.3:
872 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
873 | engines: {node: '>= 0.4.0'}
874 | dependencies:
875 | function-bind: 1.1.1
876 | dev: true
877 |
878 | /ignore-by-default/2.0.0:
879 | resolution: {integrity: sha512-+mQSgMRiFD3L3AOxLYOCxjIq4OnAmo5CIuC+lj5ehCJcPtV++QacEV7FdpzvYxH6DaOySWzQU6RR0lPLy37ckA==}
880 | engines: {node: '>=10 <11 || >=12 <13 || >=14'}
881 | dev: true
882 |
883 | /ignore/5.2.0:
884 | resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==}
885 | engines: {node: '>= 4'}
886 | dev: true
887 |
888 | /imurmurhash/0.1.4:
889 | resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=}
890 | engines: {node: '>=0.8.19'}
891 | dev: true
892 |
893 | /indent-string/4.0.0:
894 | resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
895 | engines: {node: '>=8'}
896 | dev: true
897 |
898 | /indent-string/5.0.0:
899 | resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
900 | engines: {node: '>=12'}
901 | dev: true
902 |
903 | /inflight/1.0.6:
904 | resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=}
905 | dependencies:
906 | once: 1.4.0
907 | wrappy: 1.0.2
908 | dev: true
909 |
910 | /inherits/2.0.4:
911 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
912 | dev: true
913 |
914 | /irregular-plurals/3.3.0:
915 | resolution: {integrity: sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g==}
916 | engines: {node: '>=8'}
917 | dev: true
918 |
919 | /is-binary-path/2.1.0:
920 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
921 | engines: {node: '>=8'}
922 | dependencies:
923 | binary-extensions: 2.2.0
924 | dev: true
925 |
926 | /is-core-module/2.8.1:
927 | resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==}
928 | dependencies:
929 | has: 1.0.3
930 | dev: true
931 |
932 | /is-error/2.2.2:
933 | resolution: {integrity: sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==}
934 | dev: true
935 |
936 | /is-extglob/2.1.1:
937 | resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=}
938 | engines: {node: '>=0.10.0'}
939 | dev: true
940 |
941 | /is-fullwidth-code-point/3.0.0:
942 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
943 | engines: {node: '>=8'}
944 | dev: true
945 |
946 | /is-fullwidth-code-point/4.0.0:
947 | resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
948 | engines: {node: '>=12'}
949 | dev: true
950 |
951 | /is-glob/4.0.3:
952 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
953 | engines: {node: '>=0.10.0'}
954 | dependencies:
955 | is-extglob: 2.1.1
956 | dev: true
957 |
958 | /is-module/1.0.0:
959 | resolution: {integrity: sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=}
960 | dev: true
961 |
962 | /is-number/7.0.0:
963 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
964 | engines: {node: '>=0.12.0'}
965 | dev: true
966 |
967 | /is-path-cwd/2.2.0:
968 | resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
969 | engines: {node: '>=6'}
970 | dev: true
971 |
972 | /is-path-inside/3.0.3:
973 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
974 | engines: {node: '>=8'}
975 | dev: true
976 |
977 | /is-plain-object/5.0.0:
978 | resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
979 | engines: {node: '>=0.10.0'}
980 | dev: true
981 |
982 | /is-promise/4.0.0:
983 | resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
984 | dev: true
985 |
986 | /is-typedarray/1.0.0:
987 | resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=}
988 | dev: true
989 |
990 | /is-unicode-supported/1.1.0:
991 | resolution: {integrity: sha512-lDcxivp8TJpLG75/DpatAqNzOpDPSpED8XNtrpBHTdQ2InQ1PbW78jhwSxyxhhu+xbVSast2X38bwj8atwoUQA==}
992 | engines: {node: '>=12'}
993 | dev: true
994 |
995 | /jest-worker/26.6.2:
996 | resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
997 | engines: {node: '>= 10.13.0'}
998 | dependencies:
999 | '@types/node': 17.0.8
1000 | merge-stream: 2.0.0
1001 | supports-color: 7.2.0
1002 | dev: true
1003 |
1004 | /js-string-escape/1.0.1:
1005 | resolution: {integrity: sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=}
1006 | engines: {node: '>= 0.8'}
1007 | dev: true
1008 |
1009 | /js-tokens/4.0.0:
1010 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
1011 | dev: true
1012 |
1013 | /js-yaml/3.14.1:
1014 | resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
1015 | hasBin: true
1016 | dependencies:
1017 | argparse: 1.0.10
1018 | esprima: 4.0.1
1019 | dev: true
1020 |
1021 | /jwt-decode/3.1.2:
1022 | resolution: {integrity: sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==}
1023 | dev: true
1024 |
1025 | /load-json-file/7.0.1:
1026 | resolution: {integrity: sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==}
1027 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1028 | dev: true
1029 |
1030 | /locate-path/7.0.0:
1031 | resolution: {integrity: sha512-+cg2yXqDUKfo4hsFxwa3G1cBJeA+gs1vD8FyV9/odWoUlQe/4syxHQ5DPtKjtfm6gnKbZzjCqzX03kXosvZB1w==}
1032 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1033 | dependencies:
1034 | p-locate: 6.0.0
1035 | dev: true
1036 |
1037 | /lodash/4.17.21:
1038 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
1039 | dev: true
1040 |
1041 | /lru-cache/6.0.0:
1042 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
1043 | engines: {node: '>=10'}
1044 | dependencies:
1045 | yallist: 4.0.0
1046 | dev: true
1047 |
1048 | /map-age-cleaner/0.1.3:
1049 | resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==}
1050 | engines: {node: '>=6'}
1051 | dependencies:
1052 | p-defer: 1.0.0
1053 | dev: true
1054 |
1055 | /matcher/5.0.0:
1056 | resolution: {integrity: sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==}
1057 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1058 | dependencies:
1059 | escape-string-regexp: 5.0.0
1060 | dev: true
1061 |
1062 | /md5-hex/3.0.1:
1063 | resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==}
1064 | engines: {node: '>=8'}
1065 | dependencies:
1066 | blueimp-md5: 2.19.0
1067 | dev: true
1068 |
1069 | /mem/9.0.1:
1070 | resolution: {integrity: sha512-f4uEX3Ley9FZqcFIRSBr2q43x1bJQeDvsxgkSN/BPnA7jY9Aue4sBU2dsjmpDwiaY/QY1maNCeosbUHQWzzdQw==}
1071 | engines: {node: '>=12.20'}
1072 | dependencies:
1073 | map-age-cleaner: 0.1.3
1074 | mimic-fn: 4.0.0
1075 | dev: true
1076 |
1077 | /merge-stream/2.0.0:
1078 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
1079 | dev: true
1080 |
1081 | /merge2/1.4.1:
1082 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
1083 | engines: {node: '>= 8'}
1084 | dev: true
1085 |
1086 | /micromatch/4.0.4:
1087 | resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==}
1088 | engines: {node: '>=8.6'}
1089 | dependencies:
1090 | braces: 3.0.2
1091 | picomatch: 2.3.1
1092 | dev: true
1093 |
1094 | /mimic-fn/4.0.0:
1095 | resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
1096 | engines: {node: '>=12'}
1097 | dev: true
1098 |
1099 | /minimatch/3.0.4:
1100 | resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==}
1101 | dependencies:
1102 | brace-expansion: 1.1.11
1103 | dev: true
1104 |
1105 | /ms/2.1.2:
1106 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
1107 | dev: true
1108 |
1109 | /ms/2.1.3:
1110 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
1111 | dev: true
1112 |
1113 | /nofilter/3.1.0:
1114 | resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==}
1115 | engines: {node: '>=12.19'}
1116 | dev: true
1117 |
1118 | /normalize-path/3.0.0:
1119 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
1120 | engines: {node: '>=0.10.0'}
1121 | dev: true
1122 |
1123 | /once/1.4.0:
1124 | resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
1125 | dependencies:
1126 | wrappy: 1.0.2
1127 | dev: true
1128 |
1129 | /p-defer/1.0.0:
1130 | resolution: {integrity: sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=}
1131 | engines: {node: '>=4'}
1132 | dev: true
1133 |
1134 | /p-event/5.0.1:
1135 | resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==}
1136 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1137 | dependencies:
1138 | p-timeout: 5.0.2
1139 | dev: true
1140 |
1141 | /p-limit/4.0.0:
1142 | resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
1143 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1144 | dependencies:
1145 | yocto-queue: 1.0.0
1146 | dev: true
1147 |
1148 | /p-locate/6.0.0:
1149 | resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==}
1150 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1151 | dependencies:
1152 | p-limit: 4.0.0
1153 | dev: true
1154 |
1155 | /p-map/4.0.0:
1156 | resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
1157 | engines: {node: '>=10'}
1158 | dependencies:
1159 | aggregate-error: 3.1.0
1160 | dev: true
1161 |
1162 | /p-map/5.3.0:
1163 | resolution: {integrity: sha512-SRbIQFoLYNezHkqZslqeg963HYUtqOrfMCxjNrFOpJ19WTYuq26rQoOXeX8QQiMLUlLqdYV/7PuDsdYJ7hLE1w==}
1164 | engines: {node: '>=12'}
1165 | dependencies:
1166 | aggregate-error: 4.0.0
1167 | dev: true
1168 |
1169 | /p-timeout/5.0.2:
1170 | resolution: {integrity: sha512-sEmji9Yaq+Tw+STwsGAE56hf7gMy9p0tQfJojIAamB7WHJYJKf1qlsg9jqBWG8q9VCxKPhZaP/AcXwEoBcYQhQ==}
1171 | engines: {node: '>=12'}
1172 | dev: true
1173 |
1174 | /parse-ms/2.1.0:
1175 | resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==}
1176 | engines: {node: '>=6'}
1177 | dev: true
1178 |
1179 | /path-exists/5.0.0:
1180 | resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==}
1181 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1182 | dev: true
1183 |
1184 | /path-is-absolute/1.0.1:
1185 | resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=}
1186 | engines: {node: '>=0.10.0'}
1187 | dev: true
1188 |
1189 | /path-parse/1.0.7:
1190 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
1191 | dev: true
1192 |
1193 | /path-type/4.0.0:
1194 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
1195 | engines: {node: '>=8'}
1196 | dev: true
1197 |
1198 | /picomatch/2.3.1:
1199 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
1200 | engines: {node: '>=8.6'}
1201 | dev: true
1202 |
1203 | /pkg-conf/4.0.0:
1204 | resolution: {integrity: sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==}
1205 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1206 | dependencies:
1207 | find-up: 6.2.0
1208 | load-json-file: 7.0.1
1209 | dev: true
1210 |
1211 | /plur/5.1.0:
1212 | resolution: {integrity: sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==}
1213 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
1214 | dependencies:
1215 | irregular-plurals: 3.3.0
1216 | dev: true
1217 |
1218 | /pnpm/6.25.1:
1219 | resolution: {integrity: sha512-/jvwDU8XJ3ntw1fJ5pYGN+nMqxHuXoarajc/95CrAB9+lVfjTJooiOc5BmxT7GrZzcEwdpJKMCdN3yR1ItGFMw==}
1220 | engines: {node: '>=12.17'}
1221 | hasBin: true
1222 | dev: true
1223 |
1224 | /prettier/2.5.1:
1225 | resolution: {integrity: sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==}
1226 | engines: {node: '>=10.13.0'}
1227 | hasBin: true
1228 | dev: true
1229 |
1230 | /pretty-ms/7.0.1:
1231 | resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==}
1232 | engines: {node: '>=10'}
1233 | dependencies:
1234 | parse-ms: 2.1.0
1235 | dev: true
1236 |
1237 | /queue-microtask/1.2.3:
1238 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
1239 | dev: true
1240 |
1241 | /randombytes/2.1.0:
1242 | resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
1243 | dependencies:
1244 | safe-buffer: 5.2.1
1245 | dev: true
1246 |
1247 | /readdirp/3.6.0:
1248 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
1249 | engines: {node: '>=8.10.0'}
1250 | dependencies:
1251 | picomatch: 2.3.1
1252 | dev: true
1253 |
1254 | /require-directory/2.1.1:
1255 | resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=}
1256 | engines: {node: '>=0.10.0'}
1257 | dev: true
1258 |
1259 | /resolve-cwd/3.0.0:
1260 | resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==}
1261 | engines: {node: '>=8'}
1262 | dependencies:
1263 | resolve-from: 5.0.0
1264 | dev: true
1265 |
1266 | /resolve-from/5.0.0:
1267 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
1268 | engines: {node: '>=8'}
1269 | dev: true
1270 |
1271 | /resolve/1.21.0:
1272 | resolution: {integrity: sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==}
1273 | hasBin: true
1274 | dependencies:
1275 | is-core-module: 2.8.1
1276 | path-parse: 1.0.7
1277 | supports-preserve-symlinks-flag: 1.0.0
1278 | dev: true
1279 |
1280 | /reusify/1.0.4:
1281 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
1282 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
1283 | dev: true
1284 |
1285 | /rimraf/3.0.2:
1286 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
1287 | hasBin: true
1288 | dependencies:
1289 | glob: 7.2.0
1290 | dev: true
1291 |
1292 | /rollup-plugin-terser/7.0.2_rollup@2.63.0:
1293 | resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==}
1294 | peerDependencies:
1295 | rollup: ^2.0.0
1296 | dependencies:
1297 | '@babel/code-frame': 7.16.7
1298 | jest-worker: 26.6.2
1299 | rollup: 2.63.0
1300 | serialize-javascript: 4.0.0
1301 | terser: 5.10.0
1302 | transitivePeerDependencies:
1303 | - acorn
1304 | dev: true
1305 |
1306 | /rollup/2.63.0:
1307 | resolution: {integrity: sha512-nps0idjmD+NXl6OREfyYXMn/dar3WGcyKn+KBzPdaLecub3x/LrId0wUcthcr8oZUAcZAR8NKcfGGFlNgGL1kQ==}
1308 | engines: {node: '>=10.0.0'}
1309 | hasBin: true
1310 | optionalDependencies:
1311 | fsevents: 2.3.2
1312 | dev: true
1313 |
1314 | /run-parallel/1.2.0:
1315 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
1316 | dependencies:
1317 | queue-microtask: 1.2.3
1318 | dev: true
1319 |
1320 | /safe-buffer/5.2.1:
1321 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
1322 | dev: true
1323 |
1324 | /semver/7.3.5:
1325 | resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==}
1326 | engines: {node: '>=10'}
1327 | hasBin: true
1328 | dependencies:
1329 | lru-cache: 6.0.0
1330 | dev: true
1331 |
1332 | /serialize-error/7.0.1:
1333 | resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
1334 | engines: {node: '>=10'}
1335 | dependencies:
1336 | type-fest: 0.13.1
1337 | dev: true
1338 |
1339 | /serialize-javascript/4.0.0:
1340 | resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==}
1341 | dependencies:
1342 | randombytes: 2.1.0
1343 | dev: true
1344 |
1345 | /signal-exit/3.0.6:
1346 | resolution: {integrity: sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==}
1347 | dev: true
1348 |
1349 | /slash/3.0.0:
1350 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
1351 | engines: {node: '>=8'}
1352 | dev: true
1353 |
1354 | /slash/4.0.0:
1355 | resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==}
1356 | engines: {node: '>=12'}
1357 | dev: true
1358 |
1359 | /slice-ansi/5.0.0:
1360 | resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
1361 | engines: {node: '>=12'}
1362 | dependencies:
1363 | ansi-styles: 6.1.0
1364 | is-fullwidth-code-point: 4.0.0
1365 | dev: true
1366 |
1367 | /source-map-support/0.5.21:
1368 | resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
1369 | dependencies:
1370 | buffer-from: 1.1.2
1371 | source-map: 0.6.1
1372 | dev: true
1373 |
1374 | /source-map/0.6.1:
1375 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
1376 | engines: {node: '>=0.10.0'}
1377 | dev: true
1378 |
1379 | /source-map/0.7.3:
1380 | resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==}
1381 | engines: {node: '>= 8'}
1382 | dev: true
1383 |
1384 | /sprintf-js/1.0.3:
1385 | resolution: {integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=}
1386 | dev: true
1387 |
1388 | /stack-utils/2.0.5:
1389 | resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==}
1390 | engines: {node: '>=10'}
1391 | dependencies:
1392 | escape-string-regexp: 2.0.0
1393 | dev: true
1394 |
1395 | /string-width/4.2.3:
1396 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
1397 | engines: {node: '>=8'}
1398 | dependencies:
1399 | emoji-regex: 8.0.0
1400 | is-fullwidth-code-point: 3.0.0
1401 | strip-ansi: 6.0.1
1402 | dev: true
1403 |
1404 | /string-width/5.1.0:
1405 | resolution: {integrity: sha512-7x54QnN21P+XL/v8SuNKvfgsUre6PXpN7mc77N3HlZv+f1SBRGmjxtOud2Z6FZ8DmdkD/IdjCaf9XXbnqmTZGQ==}
1406 | engines: {node: '>=12'}
1407 | dependencies:
1408 | eastasianwidth: 0.2.0
1409 | emoji-regex: 9.2.2
1410 | strip-ansi: 7.0.1
1411 | dev: true
1412 |
1413 | /strip-ansi/6.0.1:
1414 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
1415 | engines: {node: '>=8'}
1416 | dependencies:
1417 | ansi-regex: 5.0.1
1418 | dev: true
1419 |
1420 | /strip-ansi/7.0.1:
1421 | resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==}
1422 | engines: {node: '>=12'}
1423 | dependencies:
1424 | ansi-regex: 6.0.1
1425 | dev: true
1426 |
1427 | /supertap/2.0.0:
1428 | resolution: {integrity: sha512-jRzcXlCeDYvKoZGA5oRhYyR3jUIYu0enkSxtmAgHRlD7HwrovTpH4bDSi0py9FtuA8si9cW/fKommJHuaoDHJA==}
1429 | engines: {node: '>=10'}
1430 | dependencies:
1431 | arrify: 2.0.1
1432 | indent-string: 4.0.0
1433 | js-yaml: 3.14.1
1434 | serialize-error: 7.0.1
1435 | strip-ansi: 6.0.1
1436 | dev: true
1437 |
1438 | /supports-color/5.5.0:
1439 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
1440 | engines: {node: '>=4'}
1441 | dependencies:
1442 | has-flag: 3.0.0
1443 | dev: true
1444 |
1445 | /supports-color/7.2.0:
1446 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
1447 | engines: {node: '>=8'}
1448 | dependencies:
1449 | has-flag: 4.0.0
1450 | dev: true
1451 |
1452 | /supports-preserve-symlinks-flag/1.0.0:
1453 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
1454 | engines: {node: '>= 0.4'}
1455 | dev: true
1456 |
1457 | /temp-dir/2.0.0:
1458 | resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
1459 | engines: {node: '>=8'}
1460 | dev: true
1461 |
1462 | /terser/5.10.0:
1463 | resolution: {integrity: sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==}
1464 | engines: {node: '>=10'}
1465 | hasBin: true
1466 | peerDependencies:
1467 | acorn: ^8.5.0
1468 | peerDependenciesMeta:
1469 | acorn:
1470 | optional: true
1471 | dependencies:
1472 | commander: 2.20.3
1473 | source-map: 0.7.3
1474 | source-map-support: 0.5.21
1475 | dev: true
1476 |
1477 | /time-zone/1.0.0:
1478 | resolution: {integrity: sha1-mcW/VZWJZq9tBtg73zgA3IL67F0=}
1479 | engines: {node: '>=4'}
1480 | dev: true
1481 |
1482 | /to-regex-range/5.0.1:
1483 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
1484 | engines: {node: '>=8.0'}
1485 | dependencies:
1486 | is-number: 7.0.0
1487 | dev: true
1488 |
1489 | /type-fest/0.13.1:
1490 | resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
1491 | engines: {node: '>=10'}
1492 | dev: true
1493 |
1494 | /typedarray-to-buffer/3.1.5:
1495 | resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==}
1496 | dependencies:
1497 | is-typedarray: 1.0.0
1498 | dev: true
1499 |
1500 | /typescript/4.5.4:
1501 | resolution: {integrity: sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==}
1502 | engines: {node: '>=4.2.0'}
1503 | hasBin: true
1504 | dev: true
1505 |
1506 | /well-known-symbols/2.0.0:
1507 | resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==}
1508 | engines: {node: '>=6'}
1509 | dev: true
1510 |
1511 | /wrap-ansi/7.0.0:
1512 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
1513 | engines: {node: '>=10'}
1514 | dependencies:
1515 | ansi-styles: 4.3.0
1516 | string-width: 4.2.3
1517 | strip-ansi: 6.0.1
1518 | dev: true
1519 |
1520 | /wrappy/1.0.2:
1521 | resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
1522 | dev: true
1523 |
1524 | /write-file-atomic/3.0.3:
1525 | resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==}
1526 | dependencies:
1527 | imurmurhash: 0.1.4
1528 | is-typedarray: 1.0.0
1529 | signal-exit: 3.0.6
1530 | typedarray-to-buffer: 3.1.5
1531 | dev: true
1532 |
1533 | /y18n/5.0.8:
1534 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
1535 | engines: {node: '>=10'}
1536 | dev: true
1537 |
1538 | /yallist/4.0.0:
1539 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
1540 | dev: true
1541 |
1542 | /yargs-parser/21.0.0:
1543 | resolution: {integrity: sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==}
1544 | engines: {node: '>=12'}
1545 | dev: true
1546 |
1547 | /yargs/17.3.1:
1548 | resolution: {integrity: sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==}
1549 | engines: {node: '>=12'}
1550 | dependencies:
1551 | cliui: 7.0.4
1552 | escalade: 3.1.1
1553 | get-caller-file: 2.0.5
1554 | require-directory: 2.1.1
1555 | string-width: 4.2.3
1556 | y18n: 5.0.8
1557 | yargs-parser: 21.0.0
1558 | dev: true
1559 |
1560 | /yocto-queue/1.0.0:
1561 | resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
1562 | engines: {node: '>=12.20'}
1563 | dev: true
1564 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/**'
3 |
--------------------------------------------------------------------------------
/scripts/bump.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -o errexit
4 |
5 | ROOT_DIR="$(dirname $(dirname $0))"
6 |
7 | PACKAGE_NAME="$PNPM_PACKAGE_NAME"
8 |
9 | # It's the package name without "@bitty/"
10 | PACKAGE_DIR_NAME="${PACKAGE_NAME:7}"
11 |
12 | PACKAGE_DIR="$ROOT_DIR/packages/$PACKAGE_DIR_NAME"
13 |
14 | cd $PACKAGE_DIR
15 |
16 | PACKAGE_VERSION="$(node -p 'require("./package.json").version')"
17 |
18 | npm version $1 \
19 | --commit-hooks false \
20 | --git-tag-version false
21 |
22 | sleep 2
23 |
24 | git add package.json
25 |
26 | sleep 2
27 |
28 | GIT_DIR="$(git rev-parse --show-toplevel)"
29 |
30 | sleep 2
31 |
32 | if [[ $GIT_DIR == $PACKAGE_DIR ]]; then
33 | git commit -m "🔖 bump to version $PACKAGE_VERSION"
34 | else
35 | git commit -m "🔖 ($PACKAGE_DIR_NAME): bump to version $PACKAGE_VERSION"
36 | fi
37 |
38 | sleep 2
39 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | // Transpile output settings
5 | "target": "ES5",
6 | "module": "ES2015",
7 | "charset": "utf-8",
8 | "newLine": "lf",
9 | "sourceMap": true,
10 |
11 | // Type declaration settings
12 | "declaration": true,
13 | "declarationMap": true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | // Module settings
4 | "allowSyntheticDefaultImports": true,
5 | "esModuleInterop": true,
6 | "moduleResolution": "node",
7 |
8 | // Type-check settings
9 | "alwaysStrict": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "importsNotUsedAsValues": "error",
12 | "noFallthroughCasesInSwitch": true,
13 | "noImplicitReturns": true,
14 | "noUnusedLocals": true,
15 | "noUnusedParameters": true,
16 | "strict": true,
17 |
18 | // Type declaration settings
19 | "types": []
20 | }
21 | }
22 |
--------------------------------------------------------------------------------