diff --git a/.changeset/pink-falcons-enjoy.md b/.changeset/pink-falcons-enjoy.md new file mode 100644 index 0000000..8c91ba9 --- /dev/null +++ b/.changeset/pink-falcons-enjoy.md @@ -0,0 +1,5 @@ +--- +"@victorenokh/maybe.ts": minor +--- + +Implemented Task, Task Either, Task Maybe monads, implemented prisms, multiple function, namespace autoimport diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7ed0206 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 diff --git a/.eslintrc.js b/.eslintrc.js index aed9e77..3a248cd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -69,12 +69,4 @@ module.exports = { ], 'block-spacing': ['warn', 'always'], }, - overrides: [ - { - files: ['*.ts', '*.tsx'], - rules: { - '@typescript-eslint/indent': ['error', 2], - }, - }, - ], } diff --git a/.prettierrc b/.prettierrc index ab59514..ccd6800 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,5 +4,15 @@ "tabWidth": 2, "singleQuote": true, "printWidth": 60, - "bracketSpacing": true + "bracketSpacing": true, + "importOrder": [ + "^-->$", + "^->t/(.*)$", + "^->/(.*)$", + "^[./]" + ], + "importOrderSortSpecifiers": true, + "plugins": [ + "@trivago/prettier-plugin-sort-imports" + ] } diff --git a/README.md b/README.md index a8fc5c0..737ecfa 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,43 @@ To install the latest version: `npm i @victorenokh/maybe.ts` +## Namespaces auto import +Install ts-namespace-import-plugin: +`npm i -D @unsplash/ts-namespace-import-plugin` + +Extend from namespaces tsconfig: +```json +// tsconfig.json +{ + "extends": "./node_modules/@victorenokh/maybe.ts/tsconfig.namespaces.json" +} +``` + +Use project typescript version in vscode press Ctrl + Shift + p then running **TypeScript: Select TypeScript Version** command, and selectin **Use Workspace Version** refering to [this](https://github.com/unsplash/ts-namespace-import-plugin/issues/12#issuecomment-1836965622) + # Examples + +- Imagine you have a piece of text that represents data in JSON format (like a configuration file or an API response). +- The parse function takes this text as input. +- Inside the function, it tries to convert the text into a JavaScript object using JSON.parse. +- If successful, it returns the either `right` parsed object. +- If there’s an issue (for example, the text isn’t valid JSON), it returns either `left` containing Error instead. +- We are using toError function that takes anything then stringifies it and + wraps in `Error` to handle catch block +- Why Use This? + - The tryCatch approach is useful because it gracefully handles potential errors without crashing our program using `Either` monad. + It’s like saying, “Hey, let’s try to parse this JSON, and if anything goes wrong, we’ll handle it gracefully.” +```ts +import { tryCatch, toError } from '@victorenokh/maybe.ts/either' + +const parse = (text: string) => { + return tryCatch( + () => JSON.parse(text), + toError + ) +} +``` + - [Maybe](https://maybets.duckdns.org/examples/maybe.html) - [State](https://maybets.duckdns.org/examples/state.html) - [Either](https://maybets.duckdns.org/examples/either.html) @@ -19,6 +55,7 @@ To install the latest version: - [ReaderT](https://maybets.duckdns.org/examples/readerT.html) - [Lens](https://maybets.duckdns.org/examples/lens.html) - [Prism](https://maybets.duckdns.org/examples/prisms.html) +- [Task Either](https://maybets.duckdns.org/examples/task-either.html) # License The MIT License (MIT) diff --git a/esbuild.js b/esbuild.js new file mode 100644 index 0000000..f02dc82 --- /dev/null +++ b/esbuild.js @@ -0,0 +1,30 @@ +const esbuild = require('esbuild') +const { replaceTscAliasPaths } = require('tsc-alias') +/** + * @type {esbuild.BuildOptions} + */ +const baseOptions = { + platform: 'node', + outdir: 'dist', + plugins: [], + entryPoints: ['src/*.ts', 'src/**/*.ts'], +} + +esbuild.build({ + ...baseOptions, + outExtension: { '.js': '.mjs' }, + format: 'esm', +}) + +esbuild.build({ + ...baseOptions, + format: 'cjs', +}) + +replaceTscAliasPaths({ + configFile: 'tsconfig.json', + watch: false, + outDir: 'dist', + declarationDir: 'dist', + fileExtensions: '.mjs', +}) diff --git a/examples/observable.md b/examples/observable.md index 1a352c3..9f209aa 100644 --- a/examples/observable.md +++ b/examples/observable.md @@ -3,13 +3,13 @@ ## .map() ```ts const observable = O.of(42) -observable.map((num) => num.toString()).observe(console.log()) // Output: "42" +observable.map((num) => num.toString()).observe(console.log) // Output: "42" ``` ## .flatMap() ```ts const observable = O.of(42) -observable.flatMap(num => O.of(num + 1)).observe(console.log()) // Output: 43 +observable.flatMap(num => O.of(num + 1)).observe(console.log) // Output: 43 ``` diff --git a/examples/task-either.md b/examples/task-either.md new file mode 100644 index 0000000..ab6cc5d --- /dev/null +++ b/examples/task-either.md @@ -0,0 +1,29 @@ +# Task Either + +You can think of it like a function that return promise of either. + +## tryCatch() +```ts +import { toError } from "@victorenokh/maybe.ts/either" +import { tryCatch } from "@victorenokh/maybe.ts/task-either" + +const parseOrThrow = (res: Response) => { + if (!res.ok) { + throw new Error(res.statusText) + } + + return res.text() +} + +const fetchString = (url: string) => + tryCatch(() => fetch(url).then(parseOrThrow), toError) + +fetchString('https://example.com').fold( + console.error, + console.log, +) // Output: html string of example.com site +fetchString('https://example.com/non/existing/path').fold( + console.error, + console.log, +) // Ouput: Error: internal server error +``` diff --git a/jest.config.ts b/jest.config.ts index 9590e24..4fbf127 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -4,5 +4,10 @@ const config: Config.InitialOptions = { preset: 'ts-jest', verbose: true, testEnvironment: 'node', + moduleNameMapper: { + '->/(.*)': '/src/$1', + '-->': '/src/index.ts', + '->t/(.*)': '', + }, } export default config diff --git a/package-lock.json b/package-lock.json index 9694cf8..82cfb79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,30 +1,36 @@ { "name": "@victorenokh/maybe.ts", - "version": "1.9.0", + "version": "1.10.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@victorenokh/maybe.ts", - "version": "1.9.0", + "version": "1.10.2", "license": "MIT", "devDependencies": { "@changesets/cli": "^2.27.1", "@commitlint/cli": "^19.0.3", "@commitlint/config-conventional": "^19.0.3", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/jest": "^29.5.12", "@typescript-eslint/eslint-plugin": "^7.0.1", "@typescript-eslint/parser": "^7.0.1", + "@unsplash/ts-namespace-import-plugin": "^1.0.0", "esbuild": "^0.20.2", + "esbuild-ts-paths": "^1.1.3", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "husky": "^9.0.10", + "i": "^0.3.7", "jest": "^29.7.0", "lint-staged": "^15.2.2", + "npm": "^10.5.0", "prettier": "^3.2.5", "ts-jest": "^29.1.2", "ts-node": "^10.9.2", + "tsc-alias": "^1.8.8", "typescript": "^5.3.3" } }, @@ -2928,6 +2934,124 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@trivago/prettier-plugin-sort-imports": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", + "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", + "dev": true, + "dependencies": { + "@babel/generator": "7.17.7", + "@babel/parser": "^7.20.5", + "@babel/traverse": "7.23.2", + "@babel/types": "7.17.0", + "javascript-natural-sort": "0.7.1", + "lodash": "^4.17.21" + }, + "peerDependencies": { + "@vue/compiler-sfc": "3.x", + "prettier": "2.x - 3.x" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + } + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/generator": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", + "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -3295,6 +3419,12 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@unsplash/ts-namespace-import-plugin": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@unsplash/ts-namespace-import-plugin/-/ts-namespace-import-plugin-1.0.0.tgz", + "integrity": "sha512-Z/fuSAWte/OP1ctpM/8PtecGeBN358yR1rxMiVlTQ3xIvTTFNpjQuZuqkY3XfvWFQ8mvpqumQvS7hG8XnUkTWg==", + "dev": true + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -3725,6 +3855,18 @@ "node": ">=4" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -3917,6 +4059,42 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -4808,6 +4986,16 @@ "@esbuild/win32-x64": "0.20.2" } }, + "node_modules/esbuild-ts-paths": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/esbuild-ts-paths/-/esbuild-ts-paths-1.1.3.tgz", + "integrity": "sha512-qV8WVCcMhQplEfqeu1VPa7llPL9NXpEES275z8z3FHhrescVKNzLSawGOINpmPTYo+WFUiKKLwSFcM0JoQQ5eg==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "normalize-path": "^3.0.0" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -5857,6 +6045,15 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/i": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", + "integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -6023,6 +6220,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -6415,6 +6624,12 @@ "node": ">=8" } }, + "node_modules/javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", + "dev": true + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -8407,6 +8622,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -8770,6 +8991,19 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mylas": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/raouldeheer" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -8818,6 +9052,170 @@ "node": ">=0.10.0" } }, + "node_modules/npm": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.5.0.tgz", + "integrity": "sha512-Ejxwvfh9YnWVU2yA5FzoYLTW52vxHCz+MHrOFg9Cc8IFgF/6f5AGPAvb5WTay5DIUP1NIfN3VBZ0cLlGO0Ys+A==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "cli-table3", + "columnify", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "normalize-package-data", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "npmlog", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dev": true, + "workspaces": [ + "docs", + "smoke-tests", + "mock-globals", + "mock-registry", + "workspaces/*" + ], + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^7.2.1", + "@npmcli/config": "^8.0.2", + "@npmcli/fs": "^3.1.0", + "@npmcli/map-workspaces": "^3.0.4", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.1", + "@npmcli/run-script": "^7.0.4", + "@sigstore/tuf": "^2.3.1", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^18.0.2", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.3", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^7.0.1", + "ini": "^4.1.1", + "init-package-json": "^6.0.0", + "is-cidr": "^5.0.3", + "json-parse-even-better-errors": "^3.0.1", + "libnpmaccess": "^8.0.1", + "libnpmdiff": "^6.0.3", + "libnpmexec": "^7.0.4", + "libnpmfund": "^5.0.1", + "libnpmhook": "^10.0.0", + "libnpmorg": "^6.0.1", + "libnpmpack": "^6.0.3", + "libnpmpublish": "^9.0.2", + "libnpmsearch": "^7.0.0", + "libnpmteam": "^6.0.0", + "libnpmversion": "^5.0.1", + "make-fetch-happen": "^13.0.0", + "minimatch": "^9.0.3", + "minipass": "^7.0.4", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^10.0.1", + "nopt": "^7.2.0", + "normalize-package-data": "^6.0.0", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.3.0", + "npm-package-arg": "^11.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-profile": "^9.0.0", + "npm-registry-fetch": "^16.1.0", + "npm-user-validate": "^2.0.0", + "npmlog": "^7.0.1", + "p-map": "^4.0.0", + "pacote": "^17.0.6", + "parse-conflict-json": "^3.0.1", + "proc-log": "^3.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^2.1.0", + "semver": "^7.6.0", + "spdx-expression-parse": "^3.0.1", + "ssri": "^10.0.5", + "supports-color": "^9.4.0", + "tar": "^6.2.0", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.0", + "which": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -8830,123 +9228,2731 @@ "node": ">=8" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "node_modules/npm/node_modules/@colors/colors": { + "version": "1.5.0", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=12" } }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, + "inBundle": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", "dev": true, - "dependencies": { - "wrappy": "1" - } + "inBundle": true, + "license": "MIT" }, - "node_modules/onetime": { + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "inBundle": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", "dev": true, + "inBundle": true, + "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/agent": { + "version": "2.2.1", "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "7.4.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.0", + "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^7.0.0", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/query": "^3.1.0", + "@npmcli/run-script": "^7.0.2", + "bin-links": "^4.0.1", + "cacache": "^18.0.0", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^7.0.1", + "json-parse-even-better-errors": "^3.0.0", + "json-stringify-nice": "^1.1.4", + "minimatch": "^9.0.0", + "nopt": "^7.0.0", + "npm-install-checks": "^6.2.0", + "npm-package-arg": "^11.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "npmlog": "^7.0.1", + "pacote": "^17.0.4", + "parse-conflict-json": "^3.0.0", + "proc-log": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.5", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + }, + "bin": { + "arborist": "bin/index.js" + }, "engines": { - "node": ">=0.10.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/outdent": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", - "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", - "dev": true + "node_modules/npm/node_modules/@npmcli/config": { + "version": "8.2.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^4.0.0", + "ini": "^4.1.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } }, - "node_modules/p-filter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", - "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", + "node_modules/npm/node_modules/@npmcli/disparity-colors": { + "version": "3.0.0", "dev": true, + "inBundle": true, + "license": "ISC", "dependencies": { - "p-map": "^2.0.0" + "ansi-styles": "^4.3.0" }, "engines": { - "node": ">=8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, + "inBundle": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=6" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "5.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cacache": "^18.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^17.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "7.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/query": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "7.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/@sigstore/bundle": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/core": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.3.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/sign": { + "version": "2.2.3", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.2.0", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.0", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "2.3.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.0", + "tuf-js": "^2.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/verify": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.2.0", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/models": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/are-we-there-yet": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "4.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/builtins": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "18.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "5.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ci-info": { + "version": "4.0.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "4.0.3", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^5.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cli-table3": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/npm/node_modules/clone": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/color-support": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/npm/node_modules/columnify": { + "version": "1.6.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/console-control-strings": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/defaults": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/diff": { + "version": "5.2.0", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/npm/node_modules/foreground-child": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/function-bind": { + "version": "1.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/gauge": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^4.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "10.3.10", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/has-unicode": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/hasown": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "7.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "7.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "7.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "6.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ini": { + "version": "4.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^11.0.0", + "promzard": "^1.0.0", + "read": "^2.0.0", + "read-package-json": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/ip-address": { + "version": "9.0.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/npm/node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "5.0.3", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "4.0.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/is-core-module": { + "version": "2.13.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-lambda": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/jackspeak": { + "version": "2.3.6", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/npm/node_modules/jsbn": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^11.0.1", + "npm-registry-fetch": "^16.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "6.0.7", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/disparity-colors": "^3.0.0", + "@npmcli/installed-package-contents": "^2.0.2", + "binary-extensions": "^2.2.0", + "diff": "^5.1.0", + "minimatch": "^9.0.0", + "npm-package-arg": "^11.0.1", + "pacote": "^17.0.4", + "tar": "^6.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "7.0.8", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/run-script": "^7.0.2", + "ci-info": "^4.0.0", + "npm-package-arg": "^11.0.1", + "npmlog": "^7.0.1", + "pacote": "^17.0.4", + "proc-log": "^3.0.0", + "read": "^2.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "5.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "10.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "6.0.7", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.2.1", + "@npmcli/run-script": "^7.0.2", + "npm-package-arg": "^11.0.1", + "pacote": "^17.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "9.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "ci-info": "^4.0.0", + "normalize-package-data": "^6.0.0", + "npm-package-arg": "^11.0.1", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7", + "sigstore": "^2.2.0", + "ssri": "^10.0.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "7.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^16.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^16.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "5.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.3", + "@npmcli/run-script": "^7.0.2", + "json-parse-even-better-errors": "^3.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "10.2.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "13.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "7.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-json-stream": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/negotiator": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "10.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "7.2.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "6.3.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "11.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^6.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "9.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "16.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npmlog": { + "version": "7.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^4.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^5.0.0", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/pacote": { + "version": "17.0.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^7.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.10.1", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "6.0.15", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-inflight": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "read": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~1.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.6.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/sigstore": { + "version": "2.2.2", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.2.0", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.0", + "@sigstore/sign": "^2.2.3", + "@sigstore/tuf": "^2.3.1", + "@sigstore/verify": "^1.1.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.8.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 16.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.5.0", + "dev": true, + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.17", + "dev": true, + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/ssri": { + "version": "10.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.2.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/models": "2.0.0", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/wcwidth": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/npm/node_modules/which": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/which/node_modules/isexe": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm/node_modules/wide-align": { + "version": "1.1.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC" + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/outdent": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", + "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", + "dev": true + }, + "node_modules/p-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", + "dev": true, + "dependencies": { + "p-map": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { @@ -9166,6 +12172,18 @@ "node": ">=8" } }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -9296,6 +12314,15 @@ } ] }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9442,6 +12469,18 @@ "node": ">=4" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -10590,6 +13629,32 @@ } } }, + "node_modules/tsc-alias": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.8.tgz", + "integrity": "sha512-OYUOd2wl0H858NvABWr/BoSKNERw3N9GTi3rHPK8Iv4O1UyUXIrTTOAZNHsjlVpXFOhpJBVARI1s+rzwLivN3Q==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + } + }, + "node_modules/tsc-alias/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", diff --git a/package.json b/package.json index 89de577..1d5fb0f 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,7 @@ "module": "./dist/index.mjs", "typings": "./dist/index.d.ts", "scripts": { - "esm": "esbuild --out-extension:.js=.mjs --outdir=dist --platform=node --format=esm {src/*.ts,src/**/*.ts}", - "cjs": "esbuild --outdir=dist --platform=node --format=cjs {src/*.ts,src/**/*.ts}", - "build": "rm -rf dist && npm run esm && npm run cjs && tsc --emitDeclarationOnly", + "build": "rm -rf dist && node esbuild.js && tsc --emitDeclarationOnly", "release": "npm run build && changeset publish", "version-packages": "changeset version", "test-coverage": "jest --coverage", @@ -18,6 +16,7 @@ "lint": "eslint src", "lint-fix": "eslint src --fix" }, + "sideEffects": false, "exports": { ".": { "import": "./dist/index.mjs", @@ -39,6 +38,11 @@ "require": "./dist/lens/index.js", "types": "./dist/lens/index.d.ts" }, + "./prism": { + "import": "./dist/prism/index.mjs", + "require": "./dist/prism/index.js", + "types": "./dist/prism/index.d.ts" + }, "./identity": { "import": "./dist/identity/index.mjs", "require": "./dist/identity/index.js", @@ -63,6 +67,29 @@ "import": "./dist/state/index.mjs", "require": "./dist/state/index.js", "types": "./dist/state/index.d.ts" + }, + "./task": { + "import": "./dist/task/index.mjs", + "require": "./dist/task/index.js", + "types": "./dist/task/index.d.ts" + }, + "./task-either": { + "import": "./dist/task-either/index.mjs", + "require": "./dist/task-either/index.js", + "types": "./dist/task-either/index.d.ts" + }, + "./task-maybe": { + "import": "./dist/task-maybe/index.mjs", + "require": "./dist/task-maybe/index.js", + "types": "./dist/task-maybe/index.d.ts" + }, + "./functions": { + "import": "./dist/functions/index.mjs", + "require": "./dist/functions/index.js", + "types": "./dist/functions/index.d.ts" + }, + "./types": { + "types": "./dist/types/index.d.ts" } }, "repository": { @@ -86,9 +113,10 @@ "reader", "transformer", "lens", - "prisms" + "prisms", + "tasks" ], - "author": "Victor Enokh Kuptsov ", + "author": "Victor Enokh Kuptsov ", "publishConfig": { "access": "public" }, @@ -97,19 +125,25 @@ "@changesets/cli": "^2.27.1", "@commitlint/cli": "^19.0.3", "@commitlint/config-conventional": "^19.0.3", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/jest": "^29.5.12", "@typescript-eslint/eslint-plugin": "^7.0.1", "@typescript-eslint/parser": "^7.0.1", + "@unsplash/ts-namespace-import-plugin": "^1.0.0", "esbuild": "^0.20.2", + "esbuild-ts-paths": "^1.1.3", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "husky": "^9.0.10", + "i": "^0.3.7", "jest": "^29.7.0", "lint-staged": "^15.2.2", + "npm": "^10.5.0", "prettier": "^3.2.5", "ts-jest": "^29.1.2", "ts-node": "^10.9.2", + "tsc-alias": "^1.8.8", "typescript": "^5.3.3" } } diff --git a/src/either/either.ts b/src/either/either.ts index 4cfad8c..96415e2 100644 --- a/src/either/either.ts +++ b/src/either/either.ts @@ -1,5 +1,6 @@ -import { Merged } from 'src/types/merged' +import { Merged } from '->t/merged' +// {{{ types for either functions export type FoldFunction = ( lfn: (e: Left) => R, rfn: (v: Right) => R, @@ -9,6 +10,14 @@ export type MapFunction = ( fn: (v: Right) => R, ) => Either +export type ApFunction = ( + fn: Either R>, +) => Either + +export type MapLeft = ( + f: (v: Left) => R, +) => Either + export type FlatMapFunction = ( fn: (v: Right) => Either, ) => Either @@ -25,7 +34,9 @@ export type MergeFunction = ( export type AsyncMapFunction = ( fn: (v: Right) => Promise, ) => Promise> +// }}} +// {{{ interface for left /** * Represents the left side of the Either monad. * @template T - The type of the left value. @@ -48,6 +59,8 @@ export interface Left { orElse: (fn: (e: T) => Either) => Either + ap: ApFunction + asyncMap: AsyncMapFunction /** @@ -62,10 +75,18 @@ export interface Left { /** * Maps a function over the right value. * @template U - The type of the result of the mapping function. + * @param {Function} fn - The function to map over the right value. + * @returns {Left} - A new Left containing the result of applying `fn` to the right value. + */ + map: MapFunction + + /** + * Maps a function over the left value. + * @template U - The type of the result of the mapping function. * @param {Function} fn - The function to map over the left value. * @returns {Left} - A new Left containing the result of applying `fn` to the left value. */ - map: MapFunction + mapLeft: MapLeft /** * Maps a function over the right value and flattens the result. @@ -91,7 +112,9 @@ export interface Left { */ merge: MergeFunction } +// }}} +// {{{ interface for right /** * Represents the right side of the Either monad. * @template T - The type of the right value. @@ -112,50 +135,29 @@ export interface Right { */ isLeft: () => false + ap: ApFunction + asyncMap: AsyncMapFunction orElse: (fn: (e: R) => Either) => Either fold: FoldFunction - /** - * Maps a function over the right value. - * @template U - The type of the result of the mapping function. - * @param {Function} fn - The function to map over the right value. - * @returns {Right} - A new Right containing the result of applying `fn` to the right value. - */ map: MapFunction - /** - * Maps a function over the right value and flattens the result. - * @template U - The type of the result of the mapping function. - * @param {Function} fn - The function to map over the right value. - * @returns {Right} - A new Right containing the flattened result of applying `fn` to the right value. - */ + mapLeft: MapLeft + flatMap: FlatMapFunction - /** - * Ensures that a predicate `fn` holds true for the success value. - * If the predicate fails, returns an alternative failure value computed by `fr`. - * This method is applicable when the `Either` instance represents a success value. - * @template Re The type of the alternative failure value returned if the predicate fails. - * @param {function(R): boolean} fn The predicate function to be satisfied by the success value. - * @param {function(R): Re} fr The function to compute an alternative failure value if the predicate fails. - * @returns {Either} An `Either` instance with the same failure type `L` but potentially different success type. - */ ensureOrElse: EnsureOrElseFunction - /** - * Merges two Either monads into one, combining their values if both are Right, or returning the first Left value otherwise. - * @template Nr The type of the value in the second Either monad. - * @param {Either} or The Either monad to merge. - * @returns {Either>} An Either monad representing the merged result. - */ merge: MergeFunction } +// }}} export type Either = Left | Right +// {{{ function for left /** * Constructs a Left Either monad with the provided value. * @@ -177,6 +179,9 @@ export const left = (e: L): Either => ({ map: (_: (v: R) => Re) => left(e), + mapLeft: (f: (v: L) => Re): Either => + left(f(e)), + asyncMap: (_: (v: R) => Promise) => Promise.resolve>(left(e)), @@ -187,8 +192,13 @@ export const left = (e: L): Either => ({ left(e), merge: (_: Either) => left(e), + + ap: (_f: Either Re>): Either => + left(e), }) +// }}} +// {{{ function for right /** * Constructs a Right Either monad with the provided value. * @@ -212,6 +222,8 @@ export const right = ( map: (fn: (v: R) => Re) => right(fn(v)), + mapLeft: (_: (v: L) => Re): Either => right(v), + asyncMap: ( fn: (v: R) => Promise, ): Promise> => @@ -230,6 +242,9 @@ export const right = ( right(v).flatMap((cv) => or.map((ov) => ({ left: cv, right: ov })), ), + + ap: (fn: Either Re>): Either => + fn.map((fn) => fn(v)), }) /** @@ -240,6 +255,8 @@ export const right = ( * * right.fold(console.error, console.log) // Output: 42 */ +// }}} + export const of = (value: Right) => right(value) diff --git a/src/either/utils/from-maybe.ts b/src/either/utils/from-maybe.ts index a98a05d..c3c3b05 100644 --- a/src/either/utils/from-maybe.ts +++ b/src/either/utils/from-maybe.ts @@ -1,5 +1,5 @@ -import { Maybe } from '../../maybe/' -import { Either, left, right } from '../either' +import { Either, left, right } from '->/either' +import { Maybe } from '->/maybe' /** * Converts a value from the Maybe monad to an Either monad. diff --git a/src/either/utils/from-throwable.ts b/src/either/utils/from-throwable.ts index 761507b..fc1918f 100644 --- a/src/either/utils/from-throwable.ts +++ b/src/either/utils/from-throwable.ts @@ -1,21 +1,22 @@ -import { Either, left, right } from '../either' +import { Either, left, right } from '->/either' /** * Constructs a function that converts a throwable function into an `Either` * monad. * @param {(...a: T) => R} f The function to be wrapped. - * @returns {(...a: T) => Either} A function that takes the same parameters as `f` and returns an `Either`. + * @returns A function that takes the same parameters as `f` and returns an `Either`. * @template T The types of the parameters of the function `f`. * @template R The return type of the function `f`. */ export const fromThrowable = - , R>( + , R, E>( f: (...a: T) => R, + c: (e: unknown) => E, ) => - (...a: T): Either => { - try { - return right(f(...a)) - } catch (e) { - return left(e) - } + (...a: T): Either => { + try { + return right(f(...a)) + } catch (e) { + return left(c(e)) } + } diff --git a/src/either/utils/index.ts b/src/either/utils/index.ts index 4312f09..3ee6fbd 100644 --- a/src/either/utils/index.ts +++ b/src/either/utils/index.ts @@ -3,3 +3,5 @@ export * from './from-maybe' export * from './to-maybe' export * from './merge' export * from './try-catch' +export * from './is' +export * from './to-error' diff --git a/src/either/utils/is.ts b/src/either/utils/is.ts new file mode 100644 index 0000000..17b02ee --- /dev/null +++ b/src/either/utils/is.ts @@ -0,0 +1,9 @@ +import { Either, Left, Right } from '->/either' + +export const isLeft = ( + v: Either, +): v is Left => v.isLeft() + +export const isRight = ( + v: Either, +): v is Right => v.isRight() diff --git a/src/either/utils/merge.ts b/src/either/utils/merge.ts index b6cb5d0..fa0cf36 100644 --- a/src/either/utils/merge.ts +++ b/src/either/utils/merge.ts @@ -1,4 +1,4 @@ -import { Either, GetLeft, GetRight, right } from '../either' +import { Either, GetLeft, GetRight, right } from '->/either' export type GetRightFromArray< T extends Array>, diff --git a/src/either/utils/to-error.ts b/src/either/utils/to-error.ts new file mode 100644 index 0000000..3436b21 --- /dev/null +++ b/src/either/utils/to-error.ts @@ -0,0 +1,2 @@ +export const toError = (error: unknown): Error => + error instanceof Error ? error : new Error(String(error)) diff --git a/src/either/utils/to-maybe.ts b/src/either/utils/to-maybe.ts index 4abd90e..c8dc7b2 100644 --- a/src/either/utils/to-maybe.ts +++ b/src/either/utils/to-maybe.ts @@ -1,5 +1,5 @@ -import { Maybe, none, of } from '../../maybe' -import { Either } from '../either' +import { Either } from '->/either' +import { Maybe, none, of } from '->/maybe' /** * Converts a value from the Either monad to a Maybe monad. diff --git a/src/either/utils/try-catch.ts b/src/either/utils/try-catch.ts index 0ab0bfd..5591b7c 100644 --- a/src/either/utils/try-catch.ts +++ b/src/either/utils/try-catch.ts @@ -1,4 +1,4 @@ -import { Either, left, right } from '../either' +import { Either, left, right } from '->/either' /** * Executes a function in a try-catch block, returning either the result of the try function @@ -7,20 +7,16 @@ import { Either, left, right } from '../either' * @template E The type of the error produced by the catch function. * @param {() => T} tryFn The function to be executed in the try block. * @param {(reason: unknown) => E} catchFn The function to handle errors caught in the catch block. - * @param {() => void} [finallyFn] Optional function to be executed in the finally block. * @returns {Either} An Either monad containing either the result of the try function * or an error produced by the catch function. */ export const tryCatch = ( tryFn: () => T, catchFn: (reason: unknown) => E, - finallyFn?: () => void, ): Either => { try { return right(tryFn()) } catch (e) { return left(catchFn(e)) - } finally { - finallyFn?.() } } diff --git a/src/functions/index.ts b/src/functions/index.ts new file mode 100644 index 0000000..9997053 --- /dev/null +++ b/src/functions/index.ts @@ -0,0 +1 @@ +export * from './multiple' diff --git a/src/functions/multiple.ts b/src/functions/multiple.ts new file mode 100644 index 0000000..f8dfd80 --- /dev/null +++ b/src/functions/multiple.ts @@ -0,0 +1,41 @@ +import { type AbstractFn } from '->/types/abstract-fn' + +export type ReturnTypes< + A extends readonly unknown[], + T extends ((...a: A) => unknown)[], +> = { + [K in keyof T]: T[K] extends (...a: A) => infer U + ? U + : never +} + +/** + * requires at least one function to execute + * @example + * + * const add = (num: number) => (toAdd: number) => num + toAdd + * const double = (num: number) => num * 2 + * const quadriple = (num: number) => double(double(num)) + * const toString = (num: number) => num.toString() + * + * const a = multiple(add(10), double, quadriple, toString) + * + * console.log(a(50)) // Output: [ 60, 100, 200, "50" ] + * @returns result of all computations passed in + */ +export const multiple = + < + F extends AbstractFn, + T extends ((...a: Parameters) => any)[], + >( + ...fns: T extends Array<(...a: Parameters) => any> + ? [F, ...T] + : T + ) => + ( + ...a: Parameters + ): ReturnTypes, [F, ...T]> => + fns.map((fn) => fn(...a)) as ReturnTypes< + Parameters, + [F, ...T] + > diff --git a/src/functions/pipe.ts b/src/functions/pipe.ts new file mode 100644 index 0000000..94ff172 --- /dev/null +++ b/src/functions/pipe.ts @@ -0,0 +1,29 @@ +import { type AbstractFn } from '->/types/abstract-fn' + +type LastFnReturnType< + F extends Array, + Else = never, +> = F extends [...any[], (...arg: any) => infer R] + ? R + : Else + +export type Pipe< + F extends AbstractFn[], + Acc extends AbstractFn[] = [], +> = F extends [(...a: infer A) => infer R] + ? [...Acc, [(...a: A) => R]] + : F extends [(...a: infer A) => any, ...infer T] + ? T extends [(a: infer B) => any, ...any[]] + ? Pipe B]> + : Acc + : Acc + +type Input = [(a: A) => D, (b: B) => C] +type Output = Pipe> + +export const pipe = < + F extends AbstractFn, + Rest extends AbstractFn[], +>( + a: Parameters[0], +) => {} diff --git a/src/identity/identity.ts b/src/identity/identity.ts index ac065f6..25029e0 100644 --- a/src/identity/identity.ts +++ b/src/identity/identity.ts @@ -1,9 +1,10 @@ -import { Merged } from 'src/types/merged' +import { Merged } from '->t/merged' export interface Identity { map: (f: (v: T) => R) => Identity flatMap: (f: (v: T) => Identity) => Identity merge: (oi: Identity) => Identity> + ap: (f: Identity<(v: T) => R>) => Identity value: T } @@ -14,5 +15,7 @@ export const of = (value: T): Identity => ({ of(value).flatMap((left) => oi.map((right) => ({ left, right })), ), + ap: (f: Identity<(v: T) => R>): Identity => + f.map((fn) => fn(value)), value, }) diff --git a/src/index.ts b/src/index.ts index eaeb234..bd750ca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,3 +6,9 @@ export * as R from './reader' export * as RT from './readerT' export * as I from './identity' export * as L from './lens' +export * as P from './prism' +export * as T from './task' +export * as TE from './task-either' +export * as TM from './task-maybe' +export * as F from './functions' +export * as TY from './types' diff --git a/src/lens/index.ts b/src/lens/index.ts index 628aa48..bfca677 100644 --- a/src/lens/index.ts +++ b/src/lens/index.ts @@ -1,2 +1 @@ export * from './lens' -export * from './prism' diff --git a/src/lens/lens.ts b/src/lens/lens.ts index 83898f8..4bf91e5 100644 --- a/src/lens/lens.ts +++ b/src/lens/lens.ts @@ -1,3 +1,4 @@ +// {{{ Lens Interface /** * Represents a lens that can focus on a specific part (property) of an object. * @template T The type of the whole object. @@ -27,6 +28,7 @@ export interface Lens { */ compose: (bc: Lens) => Lens } +// }}} /** * Creates a lens for focusing on a specific part (property) of an object. diff --git a/src/lens/prism.ts b/src/lens/prism.ts deleted file mode 100644 index 8a0b4d3..0000000 --- a/src/lens/prism.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Maybe } from '../maybe' -import { of } from '../maybe' - -export interface Prism { - view: (v: T) => Maybe - set: (v: R, s: T) => T -} - -export const prism = ( - view: (v: T) => R, - set: Prism['set'], -): Prism => ({ - view: (v) => of(view(v)), - set, -}) - -export const composePrism = ( - ab: Prism, - bc: Prism, -): Prism => ({ - view: (a) => ab.view(a).flatMap((view) => bc.view(view)), - set: (c, a) => - ab.view(a).map((view) => ab.set(bc.set(c, view), a)) - .value!, -}) diff --git a/src/maybe/maybe.ts b/src/maybe/maybe.ts index 0f55258..15df422 100644 --- a/src/maybe/maybe.ts +++ b/src/maybe/maybe.ts @@ -1,3 +1,4 @@ +// {{{ maybe interface /** * Represents a Maybe monad, which can contain either a value of type `T` or `null`. * @template T - The type of the value contained in the Maybe monad. @@ -91,7 +92,7 @@ export interface Maybe { */ value: T | null } - +// }}} /** * Creates a Maybe monad containing the specified value. * @template T - The type of the value contained in the Maybe monad. @@ -136,11 +137,11 @@ export const of = (value: T | null): Maybe => ({ value === null ? none() : fn(value) - .then((mapped) => of(mapped)) - .catch((err) => { - error?.(err) - return none() - }), + .then((mapped) => of(mapped)) + .catch((err) => { + error?.(err) + return none() + }), get value() { return value }, @@ -149,7 +150,7 @@ export const of = (value: T | null): Maybe => ({ /** * Creates a Maybe monad representing absence of value. * @template T - The type of the value contained in the Maybe monad (implicitly `null` in this case). - * @returns {Maybe} A new Maybe monad representing absence of value. + * @returns A new Maybe monad representing absence of value. */ export const none = () => of(null) diff --git a/src/maybe/utils/from-throwable.ts b/src/maybe/utils/from-throwable.ts index 17531f5..83652c7 100644 --- a/src/maybe/utils/from-throwable.ts +++ b/src/maybe/utils/from-throwable.ts @@ -1,4 +1,4 @@ -import { of, none } from '../maybe' +import { none, of } from '->/maybe' /** * Wraps a potentially throwing function in a Maybe monad. @@ -11,10 +11,10 @@ export const fromThrowable = , R>( f: (...a: T) => R, ) => - (...a: T) => { - try { - return of(f(...a)) - } catch (e) { - return none() - } + (...a: T) => { + try { + return of(f(...a)) + } catch (e) { + return none() } + } diff --git a/src/maybe/utils/from-undefined.ts b/src/maybe/utils/from-undefined.ts index dfc50d7..b4e850d 100644 --- a/src/maybe/utils/from-undefined.ts +++ b/src/maybe/utils/from-undefined.ts @@ -1,4 +1,4 @@ -import { of, Maybe } from '../maybe' +import { Maybe, of } from '->/maybe' /** * Converts a value that may be undefined to a Maybe monad. diff --git a/src/maybe/utils/index.ts b/src/maybe/utils/index.ts index 572d5db..82ad378 100644 --- a/src/maybe/utils/index.ts +++ b/src/maybe/utils/index.ts @@ -4,3 +4,4 @@ export * from './from-undefined' export * from './merge' export * from './or' export * from './from-throwable' +export * from './is' diff --git a/src/maybe/utils/is.ts b/src/maybe/utils/is.ts new file mode 100644 index 0000000..5561393 --- /dev/null +++ b/src/maybe/utils/is.ts @@ -0,0 +1,9 @@ +import { Maybe } from '../maybe' + +export const is = (value: unknown): value is Maybe => + !!value && + typeof value === 'object' && + 'map' in value && + typeof value.map === 'function' && + 'flatMap' in value && + typeof value.flatMap === 'function' diff --git a/src/maybe/utils/merge-map.ts b/src/maybe/utils/merge-map.ts index 445b6cc..268458f 100644 --- a/src/maybe/utils/merge-map.ts +++ b/src/maybe/utils/merge-map.ts @@ -1,4 +1,4 @@ -import { Maybe } from '../maybe' +import { Maybe } from '->/maybe' /** * Merges two Maybe monads and applies a callback function to their values. diff --git a/src/maybe/utils/merge.ts b/src/maybe/utils/merge.ts index 99b49a4..bf8282a 100644 --- a/src/maybe/utils/merge.ts +++ b/src/maybe/utils/merge.ts @@ -1,4 +1,4 @@ -import { Maybe, of, UnwrapMaybe } from '../maybe' +import { Maybe, UnwrapMaybe, of } from '->/maybe' /** * Extracts the type contained in an array of Maybe monads. diff --git a/src/maybe/utils/or.ts b/src/maybe/utils/or.ts index 709d1ca..488835e 100644 --- a/src/maybe/utils/or.ts +++ b/src/maybe/utils/or.ts @@ -1,4 +1,4 @@ -import { Maybe, of } from '../maybe' +import { Maybe, of } from '->/maybe' /** * Combines multiple Maybe monads into one, returning the first non-empty Maybe monad. diff --git a/src/observable/utils/merge.ts b/src/observable/utils/merge.ts index 1832681..3e45b9f 100644 --- a/src/observable/utils/merge.ts +++ b/src/observable/utils/merge.ts @@ -2,7 +2,7 @@ import { Observable, UnwrapObservable, of, -} from '../observable' +} from '->/observable' export type UnwrapObservableArray< T extends Array>, diff --git a/src/prism/index.ts b/src/prism/index.ts new file mode 100644 index 0000000..d1c2867 --- /dev/null +++ b/src/prism/index.ts @@ -0,0 +1 @@ +export * from './prism' diff --git a/src/prism/prism.ts b/src/prism/prism.ts new file mode 100644 index 0000000..26f917d --- /dev/null +++ b/src/prism/prism.ts @@ -0,0 +1,28 @@ +import { Maybe, of as some } from '->/maybe' + +export interface Prism { + view: (v: T) => Maybe + set: (v: R, s: T) => T + compose: (bc: Prism) => Prism +} + +export const of = ( + view: (v: T) => R | null, + set: Prism['set'], +): Prism => ({ + view: (v) => some(view(v)), + set, + compose: (bc: Prism): Prism => + of( + (a) => bc.view(view(a)!).value, + (c, a) => set(bc.set(c, view(a)!), a), + ), +}) + +export const fromProp = ( + key: K, +): Prism => + of( + (v) => v[key], + (v, s) => ({ ...s, [key]: v }), + ) diff --git a/src/readerT/index.ts b/src/readerT/index.ts index b41cee8..a207615 100644 --- a/src/readerT/index.ts +++ b/src/readerT/index.ts @@ -1,4 +1,4 @@ -import { E, M, S, I } from '../' +import { E, I, M, S } from '-->' export type Acceptable = | M.Maybe diff --git a/src/state/state.ts b/src/state/state.ts index da4b54d..f352481 100644 --- a/src/state/state.ts +++ b/src/state/state.ts @@ -1,3 +1,4 @@ +// {{{ state interface /** * Represents a State monad, which encapsulates a computation that modifies a state of type `T` and produces a value of type `A`. * @template T The type of the state. @@ -26,7 +27,10 @@ export interface State { * @returns {State} A new State monad resulting from flat mapping. */ flatMap: (f: (v: A) => State) => State + + ap: (f: State R>) => State } +// }}} /** * Constructs a State monad with the provided computation. @@ -51,4 +55,6 @@ export const of = ( return fn(a).run(b) }), + ap: (f: State R>) => + of(rs).flatMap((v) => f.map((f) => f(v))), }) diff --git a/src/task-either/index.ts b/src/task-either/index.ts new file mode 100644 index 0000000..19b6382 --- /dev/null +++ b/src/task-either/index.ts @@ -0,0 +1,2 @@ +export * from './task-either' +export * from './utils' diff --git a/src/task-either/task-either.ts b/src/task-either/task-either.ts new file mode 100644 index 0000000..a20aee8 --- /dev/null +++ b/src/task-either/task-either.ts @@ -0,0 +1,76 @@ +import { Either, isRight, left } from '->/either' +import { LazyPromise } from '->/types/lazy-promise' + +// {{{ TaskEither interface +export interface TaskEither { + map: (f: (v: Right) => R) => TaskEither + flatMap: ( + f: (v: Right) => TaskEither, + ) => TaskEither + ensureOrElse: ( + p: (v: Right) => boolean, + fr: (v: Right) => Left, + ) => TaskEither + orElse: ( + f: (e: Left) => TaskEither, + ) => TaskEither + run: () => Promise> + mapLeft: (f: (v: Left) => R) => TaskEither + fold: ( + onLeft: (e: Left) => Promise | R, + onRight: (v: Right) => Promise | R, + ) => Promise +} +// }}} + +/** + * `TaskEither` represents asynchrounous computation that might + * fail. + * for asynchrounous computations that never fails use `Task` + * @see {@link https://maybets.duckdns.org/task Task} + * @returns {TaskEither} - new TaskEither + */ +export const of = ( + task: LazyPromise>, +): TaskEither => ({ + map: (f: (v: Right) => R): TaskEither => + of(() => task().then((either) => either.map(f))), + flatMap: ( + f: (v: Right) => TaskEither, + ): TaskEither => + of(() => + task().then((either) => + isRight(either) + ? f(either.right).run() + : left(either.left), + ), + ), + ensureOrElse: ( + p: (v: Right) => boolean, + fr: (v: Right) => Left, + ) => + of(() => + task().then((either) => either.ensureOrElse(p, fr)), + ), + orElse: ( + f: (e: Left) => TaskEither, + ): TaskEither => + of(() => + task().then( + (either) => + (isRight(either) + ? Promise.resolve(either) + : f(either.left).run()) as Promise< + Either + >, + ), + ), + mapLeft: (f: (v: Left) => R): TaskEither => + of(() => task().then((either) => either.mapLeft(f))), + fold: ( + onLeft: (v: Left) => Promise | R, + onRight: (v: Right) => Promise | R, + ): Promise => + task().then((either) => either.fold(onLeft, onRight)), + run: task, +}) diff --git a/src/task-either/utils/index.ts b/src/task-either/utils/index.ts new file mode 100644 index 0000000..770c2e2 --- /dev/null +++ b/src/task-either/utils/index.ts @@ -0,0 +1 @@ +export * from './try-catch' diff --git a/src/task-either/utils/try-catch.ts b/src/task-either/utils/try-catch.ts new file mode 100644 index 0000000..d80f448 --- /dev/null +++ b/src/task-either/utils/try-catch.ts @@ -0,0 +1,14 @@ +import { left, right } from '->/either' +import { TaskEither, of } from '..' + +export const tryCatch = ( + tryFn: () => Promise, + catchFn: (e: unknown) => E, +): TaskEither => + of(async () => { + try { + return right(await tryFn()) + } catch (e) { + return left(catchFn(e)) + } + }) diff --git a/src/task-maybe/index.ts b/src/task-maybe/index.ts new file mode 100644 index 0000000..558cbf9 --- /dev/null +++ b/src/task-maybe/index.ts @@ -0,0 +1 @@ +export * from './task-maybe' diff --git a/src/task-maybe/task-maybe.ts b/src/task-maybe/task-maybe.ts new file mode 100644 index 0000000..23593f5 --- /dev/null +++ b/src/task-maybe/task-maybe.ts @@ -0,0 +1,24 @@ +import { Maybe, none } from '->/maybe' +import { LazyPromise } from '->/types/lazy-promise' + +interface TaskMaybe { + run: LazyPromise> + map: (f: (v: T) => R) => TaskMaybe + flatMap: (f: (v: T) => TaskMaybe) => TaskMaybe +} + +export const of = ( + run: LazyPromise>, +): TaskMaybe => ({ + run: run, + map: (f: (v: T) => R): TaskMaybe => + of(() => run().then((value) => value.map(f))), + flatMap: (f: (v: T) => TaskMaybe): TaskMaybe => + of(() => + run().then((maybe) => + maybe.value !== null + ? f(maybe.value).run() + : none(), + ), + ), +}) diff --git a/src/task/index.ts b/src/task/index.ts new file mode 100644 index 0000000..746e7a9 --- /dev/null +++ b/src/task/index.ts @@ -0,0 +1 @@ +export * from './task' diff --git a/src/task/task.ts b/src/task/task.ts new file mode 100644 index 0000000..42fbe1e --- /dev/null +++ b/src/task/task.ts @@ -0,0 +1,38 @@ +import { LazyPromise } from '->/types/lazy-promise' + +export interface Task { + map: (f: (v: T) => R) => Task + flatMap: (f: (v: T) => Task) => Task + delay: (ms: number) => Task + run: LazyPromise +} + +/** + * `Task` represents an asynchronous computation that yields value of type `T` and **never fails**. + * for computations that might fail use `TaskEither`. + * @see {@link https://maybets.duckdns.org/task-either.md Task either} + * @template T - type that Task monad is going to produce + * @param {() => Promise} run - function to wrap in task + * @returns {Task} new task monad + */ +export const of = (run: LazyPromise): Task => ({ + map: (f: (v: T) => R) => + of(() => Promise.resolve().then(run).then(f)), + flatMap: (f: (v: T) => Task): Task => + of(() => + Promise.resolve() + .then(run) + .then((a) => f(a).run()), + ), + delay: (ms) => + of( + () => + new Promise((res) => + setTimeout( + () => Promise.resolve().then(run).then(res), + ms, + ), + ), + ), + run, +}) diff --git a/src/types/abstract-fn.ts b/src/types/abstract-fn.ts new file mode 100644 index 0000000..a9f66f2 --- /dev/null +++ b/src/types/abstract-fn.ts @@ -0,0 +1 @@ +export type AbstractFn = (...a: any) => any diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..5d139e4 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,4 @@ +export * from './lazy' +export * from './merged' +export * from './abstract-fn' +export * from './lazy-promise' diff --git a/src/types/lazy-promise.ts b/src/types/lazy-promise.ts new file mode 100644 index 0000000..d0d5173 --- /dev/null +++ b/src/types/lazy-promise.ts @@ -0,0 +1,11 @@ +import { Lazy } from './lazy' + +/** + * just like `Lazy` but returns a promise + * useful for removing nested generics + * @template T - type of lazy argument that is going to be wrapped in promise + * @see {@link Lazy} + */ +export interface LazyPromise { + (): Promise +} diff --git a/src/types/lazy.ts b/src/types/lazy.ts new file mode 100644 index 0000000..b404fef --- /dev/null +++ b/src/types/lazy.ts @@ -0,0 +1,7 @@ +/** + * Lazy argument + * @template T - Type of lazy argument + */ +export interface Lazy { + (): T +} diff --git a/tests/either.test.ts b/tests/either.test.ts index fb4de12..e6eaa57 100644 --- a/tests/either.test.ts +++ b/tests/either.test.ts @@ -1,6 +1,7 @@ import { E, M } from '../src' -import { Either, tryCatch } from '../src/either' +import { tryCatch } from '../src/either' +// {{{ Functions that helps with tests const dontCallMePls = () => { throw new Error('should not be called') } @@ -43,8 +44,10 @@ const throwable = (num: number) => { return num / 2 } +// }}} describe('either.ts', () => { + // {{{ fold it('fold', () => { const nums = [0, 2] as const @@ -63,9 +66,16 @@ describe('either.ts', () => { expect(onLeft).toHaveBeenCalled() expect(onRight).not.toHaveBeenCalled() }) - + // }}} + // {{{ fromThrowable it('fromThrowable', () => { - const wrapped = E.fromThrowable(throwable) + const correctionFn = jest.fn((e: unknown) => { + expect(e).toStrictEqual(eitherExampleError) + + return E.toError(e) + }) + + const wrapped = E.fromThrowable(throwable, correctionFn) const onLeft = jest.fn((e) => expect(e).toStrictEqual(eitherExampleError), @@ -76,13 +86,15 @@ describe('either.ts', () => { expect(onLeft).toHaveBeenCalled() expect(onRight).not.toHaveBeenCalled() + expect(correctionFn).toHaveBeenCalled() wrapped(4).fold(onLeft, onRight) expect(onLeft).toHaveBeenCalledTimes(1) expect(onRight).toHaveBeenCalled() }) - + // }}} + // {{{ map it('map', () => { const mapFn = jest.fn((number: number) => number + 1) @@ -107,7 +119,8 @@ describe('either.ts', () => { expect(left).toHaveBeenCalled() expect(right).toHaveBeenCalledTimes(1) }) - + // }}} + // {{{ flatMap it('flatMap', () => { const flatMapFn = jest.fn( (number: number): E.Either => { @@ -139,8 +152,9 @@ describe('either.ts', () => { eitherExample(0, 2).flatMap(flatMapFn) expect(flatMapFn).toHaveBeenCalledTimes(2) }) - - it('ensureOrelse', () => { + // }}} + // {{{ ensureOrElse + it('ensureOrElse', () => { validateUser({ has2Fa: true, name: '1234' }).fold( () => { throw new Error('should not be called') @@ -171,7 +185,8 @@ describe('either.ts', () => { }, ) }) - + // }}} + // {{{ fromMaybe it('fromMaybe', () => { E.fromMaybe(M.of(42), '!').fold( () => { @@ -187,7 +202,8 @@ describe('either.ts', () => { }, ) }) - + // }}} + // {{{ toMaybe it('toMaybe', () => { const eitherRight: E.Either = E.right(5) const eitherLeft: E.Either = @@ -198,7 +214,8 @@ describe('either.ts', () => { ) expect(E.toMaybe(eitherLeft).value).toBeNull() }) - + // }}} + // {{{ merge it('merge', () => { const a: E.Either = E.right(5) const b: E.Either = E.right('Hello') @@ -228,7 +245,8 @@ describe('either.ts', () => { }, ) }) - + // }}} + // {{{ merge util it('merge util', () => { const merged = E.merge[]>( E.right(4), @@ -245,7 +263,8 @@ describe('either.ts', () => { }, ) }) - + // }}} + // {{{ isLeft it('isLeft', () => { const right: E.Either = E.right('hello') const left: E.Either = E.left('bye') @@ -253,7 +272,8 @@ describe('either.ts', () => { expect(right.isLeft()).not.toBeTruthy() expect(left.isLeft()).toBeTruthy() }) - + // }}} + // {{{ isRight it('isRight', () => { const right: E.Either = E.right('hello') const left: E.Either = E.left('bye') @@ -261,7 +281,8 @@ describe('either.ts', () => { expect(right.isRight()).toBeTruthy() expect(left.isRight()).not.toBeTruthy() }) - + // }}} + // {{{ orElse it('orElse', () => { const a: E.Either = E.right('k').orElse( () => E.left('test'), @@ -287,7 +308,8 @@ describe('either.ts', () => { }, ) }) - + // }}} + // {{{ asyncMap it('asyncMap', async () => { const sleep = (ms: number): Promise => new Promise((res) => setTimeout(() => res(ms), ms)) @@ -319,7 +341,8 @@ describe('either.ts', () => { (n) => expect(n).toBe(50), ) }) - + // }}} + // {{{ of it('of', () => { E.of(42).fold( () => { @@ -328,7 +351,8 @@ describe('either.ts', () => { (n) => expect(n).toBe(42), ) }) - + // }}} + // {{{ tryCatch it('tryCatch', () => { const tryFn = jest.fn(() => { return 20 @@ -338,15 +362,9 @@ describe('either.ts', () => { throw new Error('Error') }) - const finalyFn = jest.fn() - - tryCatch( - tryFn, - () => { - dontCallMePls() - }, - finalyFn, - ).fold( + tryCatch(tryFn, () => { + dontCallMePls() + }).fold( () => dontCallMePls(), (num) => { expect(num).toBe(20) @@ -354,16 +372,88 @@ describe('either.ts', () => { ) expect(tryFn).toHaveBeenCalled() - expect(finalyFn).toHaveBeenCalled() - tryCatch( - throwableTryFn, - (reason) => String(reason), - finalyFn, + tryCatch(throwableTryFn, (reason) => + String(reason), ).fold( (e) => expect(e).toBe('Error: Error'), dontCallMePls, ) - expect(finalyFn).toHaveBeenCalledTimes(2) }) + // }}} + // {{{ mapLeft + it('mapLeft', () => { + const mapFn = jest.fn((string: string) => + string.repeat(2), + ) + + const right = E.right(40).mapLeft(mapFn) + + expect(mapFn).not.toHaveBeenCalled() + + const left = E.left('some string').mapLeft(mapFn) + + expect(mapFn).toHaveBeenCalled() + + const onLeftFn = jest.fn((str: string) => + expect(str).toBe('some stringsome string'), + ) + + const onRightFn = jest.fn((num: number) => + expect(num).toBe(40), + ) + + left.fold(onLeftFn, dontCallMePls) + right.fold(dontCallMePls, onRightFn) + + expect(onLeftFn).toHaveBeenCalled() + expect(onRightFn).toHaveBeenCalled() + }) + // }}} + // {{{ ap + it('ap', () => { + const apFn = jest.fn((num: number) => num * 2) + + const leftAp = E.left number>( + 'no fn', + ) + const rightAp = E.right< + (num: number) => number, + string + >(apFn) + + const left = E.left('error') + + left.ap(leftAp) + + expect(apFn).not.toHaveBeenCalled() + + const right = E.right(50) + + right.ap(rightAp) + + expect(apFn).toHaveBeenCalled() + }) + // }}} + // {{{ toError + it('toError', () => { + const something = 'hey' + + const error = E.toError(something) + + expect(error instanceof Error).toBe(true) + }) + // }}} + // {{{ isRight (is) + it('isRight', () => { + expect(E.isRight(E.right(null))).toBeTruthy() + expect(E.isRight(E.left(null))).toBeFalsy() + }) + // }}} + // {{{ isLeft (is) + it('isLeft', () => { + expect(E.isLeft(E.right(null))).toBeFalsy() + expect(E.isLeft(E.left(null))).toBeTruthy() + }) + // }}} }) diff --git a/tests/functions.test.ts b/tests/functions.test.ts new file mode 100644 index 0000000..809f81f --- /dev/null +++ b/tests/functions.test.ts @@ -0,0 +1,21 @@ +import { F } from '../src/' + +// {{{ function helpers +const add = (n: number) => (toAdd: number) => n + toAdd +const double = (n: number) => n * 2 +const quadriple = (n: number) => double(double(n)) +// }}} + +describe('functions', () => { + // {{{ multiple + it('multiple', () => { + const computations = F.multiple( + add(50), + double, + quadriple, + ) + + expect(computations(50)).toStrictEqual([100, 100, 200]) + }) + // }}} +}) diff --git a/tests/identity.test.ts b/tests/identity.test.ts index be1caab..04d6155 100644 --- a/tests/identity.test.ts +++ b/tests/identity.test.ts @@ -1,6 +1,7 @@ import { I } from '../src/' describe('identity.ts', () => { + // {{{ map it('map', () => { const map = jest.fn((num: number) => { expect(num).toBe(10) @@ -12,7 +13,8 @@ describe('identity.ts', () => { expect(map).toHaveBeenCalled() expect(identity.value).toBe(20) }) - + // }}} + // {{{ flatMap it('flatMap', () => { const toMerge = I.of(50) @@ -25,7 +27,18 @@ describe('identity.ts', () => { expect(flatMapFn).toHaveBeenCalled() expect(merged.value).toStrictEqual([10, 50]) }) - + // }}} + // {{{ + it('ap', () => { + const apFn = jest.fn((v: number) => v * 2) + const identityFn = I.of(apFn) + const toApply = I.of(30) + + expect(toApply.ap(identityFn).value).toBe(60) + expect(apFn).toHaveBeenCalled() + }) + // }}} + // {{{ merge it('merge', () => { const a = I.of(50) const b = I.of(500) @@ -35,4 +48,5 @@ describe('identity.ts', () => { right: 500, }) }) + // }}} }) diff --git a/tests/lens.test.ts b/tests/lens.test.ts index 72d3484..627bd79 100644 --- a/tests/lens.test.ts +++ b/tests/lens.test.ts @@ -1,6 +1,7 @@ import { Lens, from, fromProp } from '../src/lens' describe('lens.ts', () => { + // {{{ set it('set()', () => { const obj = { a: 'string' } @@ -21,7 +22,8 @@ describe('lens.ts', () => { expect(setted.a).toBe('str') expect(setted).not.toBe(obj) }) - + // }}} + // {{{ get it('get()', () => { const obj = { a: 'string' } @@ -42,7 +44,8 @@ describe('lens.ts', () => { expect(lens.view(obj)).toBe('string') expect(view).toHaveBeenCalled() }) - + // }}} + // {{{ compose it('compose()', () => { interface Nested2 { a: string @@ -88,4 +91,5 @@ describe('lens.ts', () => { newObj, ) }) + // }}} }) diff --git a/tests/maybe-utils.test.ts b/tests/maybe-utils.test.ts index bb99b07..67eca92 100644 --- a/tests/maybe-utils.test.ts +++ b/tests/maybe-utils.test.ts @@ -1,12 +1,14 @@ import { M } from '../src/index' describe('utils.ts', () => { + // {{{ or it('or', () => { const final = M.or(M.of(null), M.of(3), M.of(4)) expect(final.value).toBe(3) }) - + // }}} + // {{{ merge it('merge without nothing', () => { const merged = M.merge( M.of(42), @@ -16,7 +18,8 @@ describe('utils.ts', () => { expect(merged.value).toStrictEqual([42, 10, 'hello']) }) - + // }}} + // {{{ merge it('merge with nothing', () => { const merged = M.merge( M.of(null), @@ -26,15 +29,18 @@ describe('utils.ts', () => { expect(merged.value).toBeNull() }) - - it('fromMaybe', () => { + // }}} + // {{{ fromUndefined + it('fromUndefined', () => { expect(M.fromUndefined(42).value).toBe(42) }) - - it('fromMaybe with undefined', () => { + // }}} + // {{{ fromUndefined + it('fromUndefined with undefined', () => { expect(M.fromUndefined(undefined).value).toBeNull() }) - + // }}} + // {{{ mergeMap it('merge map', () => { const add = (a: number, b: number) => a + b @@ -43,7 +49,8 @@ describe('utils.ts', () => { expect(M.mergeMap(a, b, add).value).toBe(3) }) - + // }}} + // {{{ mergeMap it('merge map with nothing', () => { const add = (a: number, b: number) => a + b @@ -52,7 +59,8 @@ describe('utils.ts', () => { expect(M.mergeMap(a, b, add).value).toBe(null) }) - + // }}} + // {{{ fromThrowable it('fromThrowable', () => { const throwable = (num: number) => { if (num < 5) { @@ -66,4 +74,5 @@ describe('utils.ts', () => { expect(handled(0).value).toBeNull() expect(handled(6).value).toBe(':)') }) + // }}} }) diff --git a/tests/maybe.test.ts b/tests/maybe.test.ts index 5fbdacc..dae7f6c 100644 --- a/tests/maybe.test.ts +++ b/tests/maybe.test.ts @@ -1,6 +1,7 @@ import { M } from '../src/' describe('maybe.ts', () => { + // {{{ map it('map', () => { const number = M.of(42).map((num) => num * 2) @@ -18,7 +19,8 @@ describe('maybe.ts', () => { expect(mockedFunction).not.toHaveBeenCalled() }) - + // }}} + // {{{ mapNullable it('mapNullable', () => { const shouldntBeCalled = jest.fn(() => { throw new Error('shouldnt be called') @@ -33,7 +35,8 @@ describe('maybe.ts', () => { expect(c.value).toBe(null) expect(shouldntBeCalled).not.toHaveBeenCalled() }) - + // }}} + // {{{ flatMap it('flatMap', () => { const a = M.of(5) const b = M.of(52).flatMap((value) => @@ -42,7 +45,8 @@ describe('maybe.ts', () => { expect(b.value).toBe(57) }) - + // }}} + // {{{ getOrElse it('getOrElse', () => { const get = M.none().getOrElse(5) const m = M.of(10).getOrElse(6) @@ -50,7 +54,8 @@ describe('maybe.ts', () => { expect(get).toBe(5) expect(m).toBe(10) }) - + // }}} + // {{{ flatGetOrElse it('flatGetOrElse', () => { const maybeFive = M.of(5) const maybeSix = M.of(6) @@ -61,7 +66,8 @@ describe('maybe.ts', () => { expect(get.value).toBe(5) expect(m.value).toBe(5) }) - + // }}} + // {{{ merge it('merge', () => { const a = M.of(5) const b = M.of('decyat') @@ -74,7 +80,8 @@ describe('maybe.ts', () => { expect(a.merge(nullable).value).toBeNull() }) - + // }}} + // {{{ asyncMap it('asyncMap', async () => { const sleep = (ms: number): Promise => new Promise((res) => setTimeout(() => res(ms), ms)) @@ -107,7 +114,8 @@ describe('maybe.ts', () => { expect(catchError).toHaveBeenCalled() expect(withError.value).toBeNull() }) - + // }}} + // {{{ equals it('equals', () => { const a = M.of(5) const b = M.of(5) @@ -116,7 +124,8 @@ describe('maybe.ts', () => { expect(a.equals(b)).toBeTruthy() expect(a.equals(c)).not.toBeTruthy() }) - + // }}} + // {{{ apoly it('apply', () => { const double = M.of((num: number) => num * 2) const doubleNoCall = M.of((num: number) => { @@ -128,16 +137,26 @@ describe('maybe.ts', () => { M.none().apply(doubleNoCall).value, ).toBeNull() }) - + // }}} + // {{{ isNothing it('isNothing', () => { expect(M.none().isNothing()).toBeTruthy() expect(M.of(2).isNothing()).toBeFalsy() }) - + // }}} + // {{{ call it('call', () => { const fn = jest.fn(() => 0) expect(M.call(fn)).toBe(0) expect(fn).toHaveBeenCalled() + }) // }}} + // {{{ is + it('is', () => { + const maybe = M.of(30) + + expect(M.is(maybe)).toBeTruthy() + expect(M.is(40)).toBeFalsy() }) + // }}} }) diff --git a/tests/observable.test.ts b/tests/observable.test.ts index d5c0ed3..ab77fa1 100644 --- a/tests/observable.test.ts +++ b/tests/observable.test.ts @@ -1,10 +1,13 @@ import { O } from '../src' +// {{{ function to help with tests const double = (num: number): number => num * 2 const flatDouble = (num: number): O.Observable => O.of(num * 2) +// }}} describe('observable.ts', () => { + // {{{ map it('map', () => { const observable = O.of(52) const newObservable = observable.map(double) @@ -17,7 +20,8 @@ describe('observable.ts', () => { expect(observer).toHaveBeenCalled() }) - + // }}} + // {{{ flatMap it('flatMap', () => { const observable = O.of(2) const newObservable = observable.flatMap(flatDouble) @@ -30,7 +34,8 @@ describe('observable.ts', () => { expect(observer).toHaveBeenCalled() }) - + // }}} + // {{{ next it('next', () => { const observable = O.of(42) const observer = jest.fn((num: number) => @@ -42,7 +47,8 @@ describe('observable.ts', () => { expect(observer).toHaveBeenCalledTimes(2) }) - + // }}} + // {{{ dependingNext it('dependingNext', () => { const initialState = 2 const observable = O.of(initialState) @@ -58,7 +64,8 @@ describe('observable.ts', () => { expect(observer).toHaveBeenCalled() }) - + // }}} + // {{{ merge it('merge', () => { const a = O.of(2) const b = O.of(9) @@ -81,7 +88,8 @@ describe('observable.ts', () => { a.dependingNext(double) expect(merged.value).toStrictEqual([8, 18, 3]) }) - + // }}} + // {{{ unobserve it('observe.unobserve', () => { const a = O.of(4) const observer = jest.fn((_: number) => { @@ -93,7 +101,8 @@ describe('observable.ts', () => { a.next(10) expect(a.value).toBe(10) }) - + // }}} + // {{{ equals it('equals', () => { const x = 5 const f = (v: number) => O.of(v * 2) @@ -111,4 +120,5 @@ describe('observable.ts', () => { const law3_rhs = O.of(x).flatMap((x) => f(x).flatMap(g)) expect(law3_lhs.equals(law3_rhs)).toBeTruthy() }) + // }}} }) diff --git a/tests/prism.test.ts b/tests/prism.test.ts new file mode 100644 index 0000000..4a25bdb --- /dev/null +++ b/tests/prism.test.ts @@ -0,0 +1,83 @@ +import { M, P } from '../src' + +// {{{ helpers to run tests +interface Nested2 { + a: number + b: string +} + +interface Nested { + something: Nested2 +} + +interface Obj { + a: 5 + nonExisting?: string + nonExistingExisting: string | null + nested: Nested +} + +const obj: Obj = { + a: 5, + nonExistingExisting: 'hello', + nested: { + something: { + a: 42, + b: 'something', + }, + }, +} +// }}} + +describe('prism', () => { + // {{{ view + it('view', () => { + const prism: P.Prism = P.fromProp('a') + const canNotExist: P.Prism = + P.fromProp('nonExistingExisting') + + const viewed = prism.view(obj) + const viewed2 = canNotExist.view(obj) + + expect(M.is(viewed)).toBeTruthy() + expect(M.is(viewed2)).toBeTruthy() + + expect(viewed.value).toBe(5) + expect(viewed2.value).toBe('hello') + }) + // }}} + // {{{ set + it('set', () => { + const prism: P.Prism = P.fromProp( + 'nonExistingExisting', + ) + + const setted = prism.set('helloworld', obj) + + expect(setted.nonExistingExisting).toBe('helloworld') + }) + // }}} + // {{{ compose + it('compose', () => { + const a: P.Prism = P.fromProp('nested') + const b: P.Prism = + P.fromProp('something') + + const composed = a.compose(b) + + const viewed = composed.view(obj) + + expect(M.is(viewed)).toBeTruthy() + expect(viewed.value).toStrictEqual(obj.nested.something) + + const nested2: Nested2 = { + a: 50, + b: 'qwerty', + } + + const setted = composed.set(nested2, obj) + + expect(setted.nested.something).toBe(nested2) + }) + // }}} +}) diff --git a/tests/reader.test.ts b/tests/reader.test.ts index 2fc302b..9b90cc2 100644 --- a/tests/reader.test.ts +++ b/tests/reader.test.ts @@ -1,10 +1,12 @@ import { R } from '../src' +// {{{ interface for enviroments interface Env { s: number } - +// }}} describe('reader.ts', () => { + // {{{ run it('run', () => { const run = jest.fn( (env: Record) => env.someKey, @@ -18,7 +20,8 @@ describe('reader.ts', () => { ) expect(run).toHaveBeenCalledTimes(2) }) - + // }}} + // {{{ map it('map', () => { const run = jest.fn((env: Env) => env.s * 2) @@ -27,7 +30,8 @@ describe('reader.ts', () => { expect(reader.run({ s: 100 })).toBe(1000) expect(run).toHaveBeenCalled() }) - + // }}} + // {{{ flatMap it('flatMap', () => { const a = R.of((env) => env.s * 10) const b = R.of((env) => env.s * 2) @@ -40,7 +44,8 @@ describe('reader.ts', () => { expect(merged.run({ s: 10 })).toStrictEqual([100, 20]) }) - + // }}} + // {{{ ap it('ap', () => { const a = R.of((env) => env.s / 2) const b = R.of string>( @@ -49,4 +54,5 @@ describe('reader.ts', () => { expect(a.ap(b).run({ s: 58 })).toBe('29.58') }) + // }}} }) diff --git a/tests/readerT.test.ts b/tests/readerT.test.ts index 3f8d521..8f86816 100644 --- a/tests/readerT.test.ts +++ b/tests/readerT.test.ts @@ -1,5 +1,6 @@ -import { RT, M } from '../src' +import { M, RT } from '../src' +// {{{ helpers to run tests interface Env { somevalue: number | null stringValueThatMayNotExist: string | undefined @@ -18,8 +19,10 @@ const envWithoutMissingValues: Env = { const someValue: RT.ReaderT> = RT.of( (e) => M.of(e.somevalue), ) +// }}} describe('readerT.ts', () => { + // {{{ map it('map', () => { const map = jest.fn((number: number) => number * 2) @@ -29,7 +32,8 @@ describe('readerT.ts', () => { expect(map).toHaveBeenCalled() expect(runned.value).toBe(100) }) - + // }}} + // {{{ flatMap it('flatMap', () => { const run = jest.fn((enviroment: Env) => { expect(enviroment).toBe(envWithoutMissingValues) @@ -58,4 +62,5 @@ describe('readerT.ts', () => { envWithoutMissingValues.stringValueThatMayNotExist, ]) }) + // }}} }) diff --git a/tests/state.test.ts b/tests/state.test.ts index f90f0d4..b49b16c 100644 --- a/tests/state.test.ts +++ b/tests/state.test.ts @@ -1,5 +1,6 @@ import { S } from '../src' +// {{{ helpers for running tests const double = (num: number): [number, number] => [ num * 2, num * 2, @@ -8,14 +9,17 @@ const double = (num: number): [number, number] => [ const initialState = 10 const doubleState = S.of(double) +// }}} describe('state.ts', () => { + // {{{ run it('run', () => { expect(doubleState.run(initialState)).toStrictEqual([ 20, 20, ]) }) - + // }}} + // {{{ map it('map', () => { const [result, newState] = doubleState .map((num) => num.toString()) @@ -25,7 +29,8 @@ describe('state.ts', () => { expect(result).toBe('2020') expect(newState).toBe(initialState * 2) }) - + // }}} + // {{{ flatMap it('flatMap', () => { const result = doubleState .flatMap(() => S.of((num) => [num.toString(), num])) @@ -33,4 +38,17 @@ describe('state.ts', () => { expect(result).toStrictEqual(['20', 20]) }) + // }}} + // {{{ ap + it('ap', () => { + const ap = S.of((n: number) => [ + (toAdd: number) => n + toAdd, + n, + ]) + + const num = S.of((n: number) => [n, n]) + + expect(num.ap(ap).run(50)).toStrictEqual([100, 50]) + }) + // }}} }) diff --git a/tests/task-either.test.ts b/tests/task-either.test.ts new file mode 100644 index 0000000..dcd18c5 --- /dev/null +++ b/tests/task-either.test.ts @@ -0,0 +1,45 @@ +import { left, right } from '../src/either' +import { of } from '../src/task-either' + +const shouldNotBeCalled = () => { + throw new Error('should not be called') +} + +describe('task-either.ts', () => { + // {{{ map test + it('map', async () => { + const mapFn = jest.fn((num: number) => num * 2) + + const task = of(() => Promise.resolve(right(40))).map( + mapFn, + ) + + const taskWithRight = of(() => + Promise.resolve(left('some error')), + ).map(mapFn) + + const onRightFn = jest.fn((num: number) => { + expect(num).toBe(80) + }) + + const onLeftFn = jest.fn((e: string) => { + expect(e).toBe('some error') + }) + + task.fold(shouldNotBeCalled, onRightFn).then(() => { + expect(onRightFn).toHaveBeenCalled() + expect(mapFn).toHaveBeenCalled() + }) + + taskWithRight + .fold(onLeftFn, shouldNotBeCalled) + .then(() => { + expect(onLeftFn).toHaveBeenCalled() + expect(mapFn).toHaveBeenCalledTimes(1) + }) + }) + // }}} + // {{{ flatMap test + it('flatMap', () => {}) + // }}} +}) diff --git a/tests/task.test.ts b/tests/task.test.ts new file mode 100644 index 0000000..3a89c7e --- /dev/null +++ b/tests/task.test.ts @@ -0,0 +1,33 @@ +import { of } from '../src/task' + +describe('task.ts', () => { + // {{{ map + it('map', async () => { + const task = of(() => Promise.resolve(40)).map( + (num) => num * 2, + ) + + const result = await task.run() + + expect(result).toBe(80) + }) + // }}} + // {{{ flatMap + it('flatMap', async () => { + const task = of(() => Promise.resolve(50)) + const otherTask = of(() => Promise.resolve(60)) + + const taskInTask = task.flatMap(() => otherTask) + + const runned = await taskInTask.run() + + expect(runned).toBe(60) + }) + // }}} + // {{{ delay + it('delay', async () => { + const a = of(() => Promise.resolve(40)).delay(10) + + expect(await a.run()).toBe(40) + }) // }}} +}) diff --git a/tests/utils/should-not-be-called.ts b/tests/utils/should-not-be-called.ts new file mode 100644 index 0000000..5067637 --- /dev/null +++ b/tests/utils/should-not-be-called.ts @@ -0,0 +1,3 @@ +export const shouldNotBeCalled = (...args: any[]): any => { + throw new Error('should not be called') +} diff --git a/tsconfig.json b/tsconfig.json index 9eb5910..3281001 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,18 @@ "forceConsistentCasingInFileNames": true, "declaration": true, "outDir": "./dist", - "baseUrl": "./" + "baseUrl": "./", + "paths": { + "->/*": [ + "./src/*" + ], + "-->": [ + "./src/index.ts" + ], + "->t/*": [ + "./src/types/*" + ] + } }, "include": [ "src/**/*.ts" diff --git a/tsconfig.namespaces.json b/tsconfig.namespaces.json new file mode 100644 index 0000000..ecc8497 --- /dev/null +++ b/tsconfig.namespaces.json @@ -0,0 +1,53 @@ +{ + "compilerOptions": { + "plugins": [ + { + "name": "@unsplash/ts-namespace-import-plugin", + "namespaces": { + "E": { + "importPath": "@victorenokh/maybe.ts/either" + }, + "M": { + "importPath": "@victorenokh/maybe.ts/maybe" + }, + "L": { + "importPath": "@victorenokh/maybe.ts/lens" + }, + "I": { + "importPath": "@victorenokh/maybe.ts/identity" + }, + "O": { + "importPath": "@victorenokh/maybe.ts/observable" + }, + "R": { + "importPath": "@victorenokh/maybe.ts/reader" + }, + "RT": { + "importPath": "@victorenokh/maybe.ts/readerT" + }, + "S": { + "importPath": "@victorenokh/maybe.ts/state" + }, + "T": { + "importPath": "@victorenokh/maybe.ts/task" + }, + "TE": { + "importPath": "@victorenokh/maybe.ts/task-either" + }, + "TM": { + "importPath": "@victorenokh/maybe.ts/task-maybe" + }, + "F": { + "importPath": "@victorenokh/maybe.ts/functions" + }, + "TY": { + "importPath": "@victorenokh/maybe.ts/types" + }, + "P": { + "importPath": "@victorenokh/maybe.ts/prism" + } + } + } + ] + } +}