diff --git a/docs/content/contents.mdx b/docs/content/contents.mdx index 50f5848..ed6ce62 100644 --- a/docs/content/contents.mdx +++ b/docs/content/contents.mdx @@ -3,6 +3,8 @@ course: title: "Might Fail" parts: - title: "Getting Started" + slug: getting-started + filePath: /getting-started.mdx icon: "rocket" pages: - title: "❌ try, catch, finally" @@ -29,4 +31,30 @@ course: filePath: /might-and-fail.mdx slug: might-and-fail type: documentation + - title: "API Reference" + slug: api-reference + filePath: /jsdocs/variables/default.mdx + icon: "file-text" + pages: + - title: "`mightFail`" + filePath: /jsdocs/functions/mightFail.mdx + slug: api-might-fail + type: documentation + - title: "`mightFailSync`" + filePath: /jsdocs/functions/mightFailSync.mdx + slug: api-might-fail-sync + type: documentation + - title: "`Either`" + filePath: /jsdocs/type-aliases/Either.mdx + slug: api-either + type: documentation + - title: "`Fail`" + filePath: /jsdocs/functions/Fail.mdx + slug: api-fail + type: documentation + - title: "`Might`" + filePath: /jsdocs/functions/Might.mdx + slug: api-might + type: documentation + --- diff --git a/docs/content/getting-started.mdx b/docs/content/getting-started.mdx new file mode 100644 index 0000000..c455540 --- /dev/null +++ b/docs/content/getting-started.mdx @@ -0,0 +1,46 @@ +# Getting Started + +* [❌ try, catch, finally](/try-catch-finally-is-bad) +* [`mightFail`](/might-fail) +* [`mightFailSync`](/might-fail-sync) +* [Static Methods](/static-methods) +* [Either Type](/either) +* [Might & Fail](/might-and-fail) + +## Change the way you catch errors + +That's it, that's all this library helps you do. No major re-writes for your code base, no major changes at all. Just start handling your errors in a **much** better way. + +You still throw errors or let other libraries throw errors. Just stop using `try, catch, finally` and use `mightFail` or `mightFailSync` instead. + +## `catch` Sucks. Guarding is Good. + +Guarding allows you to handle your errors early and return from the function early, making them more readable and easier to reason about. + +```ts +const [ networkError, result ] = await mightFail(fetch("/posts")); +// guard against a network error +if (networkError) { + return; +} +// guard against an error response from the server +if (!result.ok) { + return; +} +const [ convertToJSONError, posts ] = await mightFail( + result.json() +); +// guard against an error converting the response to JSON +if (convertToJSONError) { + return; +} + +// success case, unnested and at the bottom of the function +posts.map((post) => console.log(post.title)); +``` + +The success case is now the only code that is **not** nested in another block. It's also at the very bottom of the function making it easy to find. + + + The sucess case is always at the bottom of the function. All of your error handling logic is next to where the error might occur. + diff --git a/docs/content/home.mdx b/docs/content/home.mdx index 5fdb454..cec5f8f 100644 --- a/docs/content/home.mdx +++ b/docs/content/home.mdx @@ -5,8 +5,6 @@ A TypeScript library for handling async and sync errors without `try` and `catch This works for **sync** and **async** code, and you can choose the error handling style that you like. -Check out the motivation section for why `try,catch,finally` blocks are bad. - ## Install @@ -88,10 +86,10 @@ import { mightFail } from "@might/fail" - + ```ts import { mightFail } from "might-fail" -const { error: networkError, result } = await mightFail(fetch("/posts")) +const [networkError, result] = await mightFail(fetch("/posts")) if (networkError) { // handle network error @@ -103,7 +101,7 @@ if (!result.ok) { return } -const { error: convertToJSONError, result: posts } = await mightFail( +const [convertToJSONError, posts] = await mightFail( result.json() ) @@ -115,10 +113,10 @@ if (convertToJSONError) { posts.map((post) => console.log(post.title)) ``` - + ```ts -import { mightFail } from "might-fail/tuple" -const [networkError, result] = await mightFail(fetch("/posts")) +import { mightFail } from "might-fail" +const { error: networkError, result } = await mightFail(fetch("/posts")) if (networkError) { // handle network error @@ -130,7 +128,7 @@ if (!result.ok) { return } -const [convertToJSONError, posts] = await mightFail( +const { error: convertToJSONError, result: posts } = await mightFail( result.json() ) diff --git a/docs/content/jsdocs/functions/Fail.mdx b/docs/content/jsdocs/functions/Fail.mdx new file mode 100644 index 0000000..a217888 --- /dev/null +++ b/docs/content/jsdocs/functions/Fail.mdx @@ -0,0 +1,19 @@ +# Function: Fail() + +```ts +function Fail(error: unknown): Either +``` + +A constructor function that takes an error and returns an `Either` object with undefined as the result and the error as the error. + +The error will **always** be an instance of Error. + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `error` | `unknown` | | + +## Returns + +[`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`undefined`\> diff --git a/docs/content/jsdocs/functions/Might.mdx b/docs/content/jsdocs/functions/Might.mdx new file mode 100644 index 0000000..ba0f0d7 --- /dev/null +++ b/docs/content/jsdocs/functions/Might.mdx @@ -0,0 +1,23 @@ +# Function: Might() + +```ts +function Might(result: NonUndefined): Either +``` + +A pure constructor function that takes a non-null value and returns an `Either` object with the value as the result and undefined as the error. + +## Type Parameters + +| Type Parameter | +| ------ | +| `T` | + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `result` | `NonUndefined`\<`T`\> | | + +## Returns + +[`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`T`\> diff --git a/docs/content/jsdocs/functions/mightFail.mdx b/docs/content/jsdocs/functions/mightFail.mdx new file mode 100644 index 0000000..9422a79 --- /dev/null +++ b/docs/content/jsdocs/functions/mightFail.mdx @@ -0,0 +1,51 @@ +# Function: mightFail() + +```ts +function mightFail(promise: Promise): Promise> +``` + +Wraps a promise in an Either to safely handle both its resolution and rejection. This function +takes a Promise of type T and returns a Promise which resolves with an object. This object +either contains a 'result' of type T if the promise resolves successfully, or an 'error' of type Error +if the promise is rejected. + +## Type Parameters + +| Type Parameter | Description | +| ------ | ------ | +| `T` | The type of the result value. | + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `promise` | `Promise`\<`T`\> | The promise to be wrapped in an Either. This is an asynchronous operation that should resolve with a value of type T or reject with an Error. | + +## Returns + +`Promise`\<[`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`T`\>\> + +A Promise that resolves with an Either. This Either is a `Success` with +the 'result' property set to the value resolved by the promise if successful, and 'error' as undefined. +In case of failure, it's a `Failure` with 'result' as undefined and 'error' of type Error. `error` will **always** be an instance of Error. + +## Example + +```ts +// Example of wrapping an async function that might fail: +async function fetchData(url: string): Promise { + const response = await fetch(url); + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.text(); +} + +const {error, result} = await mightFail(fetchData('https://example.com')); + +if (error) { + console.error('Fetching failed:', error.message); + return; +} +console.log('Fetched data:', result); +``` diff --git a/docs/content/jsdocs/functions/mightFailFunction.mdx b/docs/content/jsdocs/functions/mightFailFunction.mdx new file mode 100644 index 0000000..415be1d --- /dev/null +++ b/docs/content/jsdocs/functions/mightFailFunction.mdx @@ -0,0 +1,21 @@ +# Function: mightFailFunction() + +```ts +function mightFailFunction(promise: Promise): Promise> +``` + +## Type Parameters + +| Type Parameter | +| ------ | +| `T` | + +## Parameters + +| Parameter | Type | +| ------ | ------ | +| `promise` | `Promise`\<`T`\> | + +## Returns + +`Promise`\<[`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`T`\>\> diff --git a/docs/content/jsdocs/functions/mightFailSync.mdx b/docs/content/jsdocs/functions/mightFailSync.mdx new file mode 100644 index 0000000..1ea830b --- /dev/null +++ b/docs/content/jsdocs/functions/mightFailSync.mdx @@ -0,0 +1,43 @@ +# Function: mightFailSync() + +```ts +function mightFailSync(func: () => T): Either +``` + +Wraps a synchronous function in an Either type to safely handle exceptions. This function +executes a provided function that returns a value of type T, capturing any thrown errors. +It returns an object that either contains a 'result' of type T if the function succeeds, +or an 'error' of type Error if the function throws an error. + +## Type Parameters + +| Type Parameter | Description | +| ------ | ------ | +| `T` | The type of the result value.◊ | + +## Parameters + +| Parameter | Type | Description | +| ------ | ------ | ------ | +| `func` | () => `T` | A wrapper function that is expected to invoke the throwing function. That function should return a value of type T or throw an error. | + +## Returns + +[`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`T`\> + +An object that is either a `Success` with the result property set to the value returned by `func`, + or a `Failure` with the error property set to the caught error. `Success` has a 'result' of type T + and 'error' as null. `Failure` has 'result' as null and 'error' of type Error. + +## Example + +```ts +// Example of wrapping a synchronous function that might throw an error: +const {error, result} = mightFailSync(() => JSON.parse("")); + +if (error) { + console.error('Parsing failed:', error); + return; +} +console.log('Parsed object:', result); +``` diff --git a/docs/content/jsdocs/index.mdx b/docs/content/jsdocs/index.mdx new file mode 100644 index 0000000..68bd396 --- /dev/null +++ b/docs/content/jsdocs/index.mdx @@ -0,0 +1,29 @@ +# might-fail + +## References + +### makeMightFail + +Re-exports makeMightFail + +*** + +### makeMightFailSync + +Re-exports makeMightFailSync + +## Type Aliases + +- [Either](https://mightfail.dev/type-aliases/Either.mdx) + +## Variables + +- [default](https://mightfail.dev/variables/default.mdx) + +## Functions + +- [Fail](https://mightfail.dev/functions/Fail.mdx) +- [Might](https://mightfail.dev/functions/Might.mdx) +- [mightFail](https://mightfail.dev/functions/mightFail.mdx) +- [mightFailFunction](https://mightfail.dev/functions/mightFailFunction.mdx) +- [mightFailSync](https://mightfail.dev/functions/mightFailSync.mdx) diff --git a/docs/content/jsdocs/type-aliases/Either.mdx b/docs/content/jsdocs/type-aliases/Either.mdx new file mode 100644 index 0000000..d970530 --- /dev/null +++ b/docs/content/jsdocs/type-aliases/Either.mdx @@ -0,0 +1,21 @@ +# Type Alias: Either\ + +```ts +type Either: { + error: Error; + result: undefined; + } & [Error, undefined] | { + error: undefined; + result: T; + } & [undefined, T]; +``` + +Either type represents a data structure that encapsulates a successful result or an Error. +It wraps the result of a Promise in an object, making it easier to handle errors by returning +an object that either contains a 'result' value of type T (if successful), or an 'error' of type Error. + +## Type Parameters + +| Type Parameter | Description | +| ------ | ------ | +| `T` | The type of the result value. | diff --git a/docs/content/jsdocs/variables/default.mdx b/docs/content/jsdocs/variables/default.mdx new file mode 100644 index 0000000..57d9254 --- /dev/null +++ b/docs/content/jsdocs/variables/default.mdx @@ -0,0 +1,25 @@ +# Variable: default + +```ts +default: { + Fail: (error: unknown) => Either; + makeMightFail: (func: T) => (...funcArgs: Parameters) => Promise>>>; + makeMightFailSync: (func: T) => (...funcArgs: Parameters) => Either>; + Might: (result: NonUndefined) => Either; + mightFail: MightFail<"standard">; + mightFailFunction: MightFailFunction<"standard">; + mightFailSync: (func: () => T) => Either; +}; +``` + +## Type declaration + +| Name | Type | +| ------ | ------ | +| `Fail` | (`error`: `unknown`) => [`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`undefined`\> | +| `makeMightFail` | \<`T`\>(`func`: `T`) => (...`funcArgs`: `Parameters`\<`T`\>) => `Promise`\<[`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`UnwrapPromise`\<`ReturnType`\<`T`\>\>\>\> | +| `makeMightFailSync` | \<`T`\>(`func`: `T`) => (...`funcArgs`: `Parameters`\<`T`\>) => [`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`ReturnType`\<`T`\>\> | +| `Might` | \<`T`\>(`result`: `NonUndefined`\<`T`\>) => [`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`T`\> | +| `mightFail` | `MightFail`\<`"standard"`\> | +| `mightFailFunction` | `MightFailFunction`\<`"standard"`\> | +| `mightFailSync` | \<`T`\>(`func`: () => `T`) => [`Either`](https://mightfail.dev/type-aliases/Either.mdx)\<`T`\> | diff --git a/docs/content/mightFail.mdx b/docs/content/mightFail.mdx index 07c9148..63fe85e 100644 --- a/docs/content/mightFail.mdx +++ b/docs/content/mightFail.mdx @@ -2,12 +2,43 @@ # `mightFail` Async -## Wrap Promise in `mightFail` +## Wrap Promise + +Simply wrap any promise in `mightFail` and await the result. + +You will get and `Either` object that contains either an error or the result. Never both. + +```ts +const EitherObject = await mightFail(fetch("/posts")); +``` + +But **don't** store the `Either` object directly. Instead, destructure it in the same statement. + +```ts +// tuple destructuring +const [ error, result ] = await mightFail(fetch("/posts")); + +// object destructuring +const { error, result } = await mightFail(fetch("/posts")); + +// go destructuring +// import { mightFail } from "might-fail/go"; +const [ result, error ] = await mightFail(fetch("/posts")); +``` + +You can choose to destructure this object as a tuple or as an object. Or as a backwards tuple if you prefer it that way. + +We think that the **tuple** option is the best, but you do you. + +## Guard + +Once you've awaited and destructured the `Either` object, use guard clauses to handle the error, and handle the success case at the end. - + + ```ts -const { error: networkError, result } = await mightFail(fetch("/posts")); +const [ networkError, result ] = await mightFail(fetch("/posts")); if (networkError) { // handle network error @@ -19,7 +50,7 @@ if (!result.ok) { return; } -const { error: convertToJSONError, result: posts } = await mightFail( +const [convertToJSONError, posts] = await mightFail( result.json() ); @@ -32,9 +63,9 @@ posts.map((post) => console.log(post.title)); ``` - + ```ts -const [ networkError, result ] = await mightFail(fetch("/posts")); +const { error: networkError, result } = await mightFail(fetch("/posts")); if (networkError) { // handle network error @@ -46,7 +77,7 @@ if (!result.ok) { return; } -const [convertToJSONError, posts] = await mightFail( +const { error: convertToJSONError, result: posts } = await mightFail( result.json() ); @@ -58,6 +89,7 @@ if (convertToJSONError) { posts.map((post) => console.log(post.title)); ``` + ```ts const [ result, networkError ] = await mightFail(fetch("/posts")); @@ -86,13 +118,15 @@ posts.map((post) => console.log(post.title)); -## Or Wrap Async Function in `makeMightFail` +## `makeMightFail` + +You also have the option to make your own `mightFail` wrapper function. Pass in any async function to `makeMightFail` and it will return a `mightFail` wrapper function for you to use. - + ```ts const get = makeMightFail(axios.get); -const { error, result } = await get("/posts"); +const [ error, result ] = await get("/posts"); if (error) { // handle error @@ -103,10 +137,10 @@ const posts = result.data posts.map((post) => console.log(post.title)); ``` - + ```ts const get = makeMightFail(axios.get); -const [ error, result ] = await get("/posts"); +const { error, result } = await get("/posts"); if (error) { // handle error diff --git a/docs/content/mightFailSync.mdx b/docs/content/mightFailSync.mdx index 76ddfd3..e181726 100644 --- a/docs/content/mightFailSync.mdx +++ b/docs/content/mightFailSync.mdx @@ -3,6 +3,19 @@ ## Wrap throwing functions in `mightFailSync` + + +```ts +const [error, result] = mightFailSync(() => JSON.parse("")); // JSON.parse might throw +if (error) { + console.error('Parsing failed:', error); + return +} +console.log('Parsed object:', result); +``` + + + ```ts const {error, result} = mightFailSync(() => JSON.parse("")); // JSON.parse might throw if (error) { @@ -11,9 +24,39 @@ if (error) { } console.log('Parsed object:', result); ``` + + +```ts +const [result, error] = mightFailSync(() => JSON.parse("")); // JSON.parse might throw +if (error) { + console.error('Parsing failed:', error); + return +} +console.log('Parsed object:', result); +``` + + ## Or Wrap Sync Function in `makeMightFailSync` + + +```ts +function parseJSON(jsonString: string) { + return JSON.parse(jsonString); // This might throw +} +const safeParseJSON = makeMightFailSync(parseJSON); + +const [error, result] = safeParseJSON(""); + +if (error) { + console.error("Parsing failed:", error); + return; +} +console.log("Parsed object:", result); +``` + + ```ts function parseJSON(jsonString: string) { return JSON.parse(jsonString); // This might throw @@ -27,4 +70,22 @@ if (error) { return; } console.log("Parsed object:", result); -``` \ No newline at end of file +``` + + +```ts +function parseJSON(jsonString: string) { + return JSON.parse(jsonString); // This might throw +} +const safeParseJSON = makeMightFailSync(parseJSON); + +const [result, error] = safeParseJSON(""); + +if (error) { + console.error("Parsing failed:", error); + return; +} +console.log("Parsed object:", result); +``` + + \ No newline at end of file diff --git a/docs/content/try-catch-finally-is-bad.mdx b/docs/content/try-catch-finally-is-bad.mdx index 5452438..7dba464 100644 --- a/docs/content/try-catch-finally-is-bad.mdx +++ b/docs/content/try-catch-finally-is-bad.mdx @@ -11,7 +11,7 @@ This mostly happens at the most "user facing" part of the code like an api endpo Guarding allows you to handle your errors early and return from the function early, making them more readable and easier to reason about. ```ts -const { error: networkError, result } = await mightFail(fetch("/posts")); +const [ networkError, result ] = await mightFail(fetch("/posts")); // guard against a network error if (networkError) { return; @@ -20,7 +20,7 @@ if (networkError) { if (!result.ok) { return; } -const { error: convertToJSONError, result: posts } = await mightFail( +const [ convertToJSONError, posts ] = await mightFail( result.json() ); // guard against an error converting the response to JSON @@ -105,4 +105,3 @@ console.log(something()) ``` Can every single dev in your team understand what the above code will print out? - diff --git a/examples/mightFailBasicTuple.ts b/examples/mightFailBasicTuple.ts index 382609c..f69fffb 100644 --- a/examples/mightFailBasicTuple.ts +++ b/examples/mightFailBasicTuple.ts @@ -1,7 +1,7 @@ -import { mightFail } from "../src/tuple" +import { mightFail } from "../src" -async function main() { - const [result, error] = await mightFail(Promise.resolve({ message: "success" })) +async function success() { + const [error, result] = await mightFail(Promise.resolve({ message: "success" })) if (error) { console.error(error) return @@ -9,4 +9,15 @@ async function main() { console.log(result.message) } -main() +success() + +async function error() { + const [error, result] = await mightFail<{ message: string }>(Promise.reject("error")) + if (error) { + console.error(error) + return + } + console.log(result.message) +} + +error() diff --git a/jsr.json b/jsr.json index ea6e460..9d0f5f8 100644 --- a/jsr.json +++ b/jsr.json @@ -3,8 +3,7 @@ "version": "0.5.1", "exports": { ".": "./src/index.ts", - "./go": "./src/go/index.ts", - "./tuple": "./src/tuple/index.ts" + "./go": "./src/go/index.ts" }, "license": "MIT" } diff --git a/package-lock.json b/package-lock.json index 17b127a..1eab93d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,68 @@ { "name": "might-fail", - "version": "0.4.1", + "version": "0.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "might-fail", - "version": "0.4.1", + "version": "0.5.1", "license": "MIT", "devDependencies": { + "jsdoc-to-markdown": "^9.0.2", + "typedoc": "^0.26.8", + "typedoc-plugin-markdown": "^4.2.9", "typescript": "^5.6.2", "vitest": "^2.1.1" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -387,6 +437,53 @@ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, + "node_modules/@jsdoc/salty": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.8.tgz", + "integrity": "sha512-5e+SFVavj1ORKlKaKr2BmTOekmXbelU7dC0cDkQLqag7xfuTPuGMUFx7KWJuv4bYZrTsoL2Z18VVCOKYxzoHcg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=v12.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.22.5", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.5.tgz", @@ -595,12 +692,115 @@ "win32" ] }, + "node_modules/@shikijs/core": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.21.0.tgz", + "integrity": "sha512-zAPMJdiGuqXpZQ+pWNezQAk5xhzRXBNiECFPcJLtUdsFM3f//G95Z15EHTnHchYycU8kIIysqGgxp8OVSj1SPQ==", + "dev": true, + "dependencies": { + "@shikijs/engine-javascript": "1.21.0", + "@shikijs/engine-oniguruma": "1.21.0", + "@shikijs/types": "1.21.0", + "@shikijs/vscode-textmate": "^9.2.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.3" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.21.0.tgz", + "integrity": "sha512-jxQHNtVP17edFW4/0vICqAVLDAxmyV31MQJL4U/Kg+heQALeKYVOWo0sMmEZ18FqBt+9UCdyqGKYE7bLRtk9mg==", + "dev": true, + "dependencies": { + "@shikijs/types": "1.21.0", + "@shikijs/vscode-textmate": "^9.2.2", + "oniguruma-to-js": "0.4.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.21.0.tgz", + "integrity": "sha512-AIZ76XocENCrtYzVU7S4GY/HL+tgHGbVU+qhiDyNw1qgCA5OSi4B4+HY4BtAoJSMGuD/L5hfTzoRVbzEm2WTvg==", + "dev": true, + "dependencies": { + "@shikijs/types": "1.21.0", + "@shikijs/vscode-textmate": "^9.2.2" + } + }, + "node_modules/@shikijs/types": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.21.0.tgz", + "integrity": "sha512-tzndANDhi5DUndBtpojEq/42+dpUF2wS7wdCDQaFtIXm3Rd1QkrcVgSSRLOvEwexekihOXfbYJINW37g96tJRw==", + "dev": true, + "dependencies": { + "@shikijs/vscode-textmate": "^9.2.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.2.2.tgz", + "integrity": "sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==", + "dev": true + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@vitest/expect": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", @@ -708,6 +908,36 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -717,6 +947,39 @@ "node": ">=12" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -726,6 +989,48 @@ "node": ">=8" } }, + "node_modules/cache-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-3.0.0.tgz", + "integrity": "sha512-LDGNWYv/tqRWAAZxMy75PIYynaIuhcyoyjJtwA7X5uMZjdzvGm+XmTey/GXUy2EJ+lwc2eBFzFYxjvNYyE/0Iw==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "^0.1.1" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chai": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", @@ -742,6 +1047,57 @@ "node": ">=12" } }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/check-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", @@ -751,6 +1107,100 @@ "node": ">= 16" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/command-line-args": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.0.tgz", + "integrity": "sha512-zDdHxHzlCp/gA1gy0VtPK3YL0Aob3ijJdwZ7H3HSl55hh8EziLtRlyj/od8EGRJfX8IjussC/mQkScl2Ms5Suw==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "find-replace": "^5.0.1", + "lodash.camelcase": "^4.3.0", + "typical": "^7.1.1" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/command-line-usage": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.3.tgz", + "integrity": "sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "chalk-template": "^0.4.0", + "table-layout": "^4.1.0", + "typical": "^7.1.1" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/common-sequence": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", + "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha512-n7LBL1zBzYdTpF1mx5DNcZnZn05CWIdsdvtPL4MosvqbBUK3Rq6VWEtGUuF3Y0s9/CIhMejezqlSkP6TnCJ/9g==", + "dev": true, + "dependencies": { + "walk-back": "^2.0.1" + } + }, + "node_modules/config-master/node_modules/walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha512-Nb6GvBR8UWX1D+Le+xUq0+Q1kFmRBIWVrfLnQAOmcpEzA9oAxwJ9gIr36t9TWYfzvWRvuMtjHiVsJYEkXWaTAQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/current-module-paths": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/current-module-paths/-/current-module-paths-1.1.2.tgz", + "integrity": "sha512-H4s4arcLx/ugbu1XkkgSvcUZax0L6tXUqnppGniQb8l5VjUKGHoayXE5RiriiPhYDd+kjZnaok1Uig13PKtKYQ==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -777,6 +1227,66 @@ "node": ">=6" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dmd": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-7.0.7.tgz", + "integrity": "sha512-UXNLJkci/tiVNct+JgrpfTlSs8cSyLbR3q4xkYQ4do6cRCUPj0HodfMsBLPhC7KG3qGRp1YJgfNjdgCrYEcHWQ==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^3.0.0", + "common-sequence": "^2.0.2", + "file-set": "^5.2.2", + "handlebars": "^4.7.8", + "marked": "^4.3.0", + "walk-back": "^5.1.1" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -815,6 +1325,15 @@ "@esbuild/win32-x64": "0.21.5" } }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -824,15 +1343,90 @@ "@types/estree": "^1.0.0" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-set": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-5.2.2.tgz", + "integrity": "sha512-/KgJI1V/QaDK4enOk/E2xMFk1cTWJghEr7UmWiRZfZ6upt6gQCfMn4jJ7aOm64OKurj4TaVnSSgSDqv5ZKYA3A==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "fast-glob": "^3.3.2" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-replace": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz", + "integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" @@ -847,6 +1441,275 @@ "node": "*" } }, + "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/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", + "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.3.tgz", + "integrity": "sha512-Nu7Sf35kXJ1MWDZIMAuATRQTg1iIPdzh7tqJ6jjvaU/GfDf+qi5UV8zJR3Mo+/pYFvm8mzay4+6O5EWigaQBQw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^14.1.1", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc-api": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-9.3.1.tgz", + "integrity": "sha512-pgZ5nrLnzF8Swxbv5OV8RYAoM/S3Cbf1UHncNYMRCQwU4KlCfg5bz5/VZlg0a1EATSHclIBf9Hm55GkXz0VItA==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^3.0.0", + "current-module-paths": "^1.1.2", + "file-set": "^5.2.0", + "jsdoc": "^4.0.3", + "object-to-spawn-args": "^2.0.1", + "walk-back": "^5.1.1" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/jsdoc-parse": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.2.4.tgz", + "integrity": "sha512-MQA+lCe3ioZd0uGbyB3nDCDZcKgKC7m/Ivt0LgKZdUoOlMJxUWJQ3WI6GeyHp9ouznKaCjlp7CU9sw5k46yZTw==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "find-replace": "^5.0.1", + "lodash.omit": "^4.5.0", + "sort-array": "^5.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdoc-to-markdown": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-9.0.2.tgz", + "integrity": "sha512-4T/7sCxq5RDXT37inCpVLetXOyjaFCMtVYH4Yvyfk/0v2aksMn74FqYdtSOc/+wceu+5ItJop6krCtGZjpJTxA==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "command-line-args": "^6.0.0", + "command-line-usage": "^7.0.3", + "config-master": "^3.1.0", + "dmd": "^7.0.7", + "jsdoc-api": "^9.3.1", + "jsdoc-parse": "^6.2.4", + "walk-back": "^5.1.1" + }, + "bin": { + "jsdoc2md": "bin/cli.js" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "latest" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "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", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", + "dev": true + }, "node_modules/loupe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", @@ -856,6 +1719,12 @@ "get-func-name": "^2.0.1" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/magic-string": { "version": "0.30.11", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", @@ -865,6 +1734,219 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -889,6 +1971,33 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/object-to-spawn-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", + "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/oniguruma-to-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "dev": true, + "dependencies": { + "regex": "^4.3.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/pathe": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", @@ -910,6 +2019,18 @@ "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", @@ -938,6 +2059,70 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/regex": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", + "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==", + "dev": true + }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rollup": { "version": "4.22.5", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.5.tgz", @@ -973,12 +2158,79 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/shiki": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.21.0.tgz", + "integrity": "sha512-apCH5BoWTrmHDPGgg3RF8+HAAbEL/CdbYr8rMw7eIrdhCkZHdVGat5mMNlRtd1erNG01VPMIKHNQ0Pj2HMAiog==", + "dev": true, + "dependencies": { + "@shikijs/core": "1.21.0", + "@shikijs/engine-javascript": "1.21.0", + "@shikijs/engine-oniguruma": "1.21.0", + "@shikijs/types": "1.21.0", + "@shikijs/vscode-textmate": "^9.2.2", + "@types/hast": "^3.0.4" + } + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, + "node_modules/sort-array": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-5.0.0.tgz", + "integrity": "sha512-Sg9MzajSGprcSrMIxsXyNT0e0JB47RJRfJspC+7co4Z5BdNsNl8FmWI+lXEpyKq+vkMG6pHgAhqyCO+bkDTfFQ==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "typical": "^7.1.1" + }, + "engines": { + "node": ">=12.17" + }, + "peerDependencies": { + "@75lb/nature": "^0.1.1" + }, + "peerDependenciesMeta": { + "@75lb/nature": { + "optional": true + } + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -988,6 +2240,16 @@ "node": ">=0.10.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -1000,6 +2262,57 @@ "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", "dev": true }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table-layout": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz", + "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "wordwrapjs": "^5.1.0" + }, + "engines": { + "node": ">=12.17" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -1039,6 +2352,71 @@ "node": ">=14.0.0" } }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/typedoc": { + "version": "0.26.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.8.tgz", + "integrity": "sha512-QBF0BMbnNeUc6U7pRHY7Jb8pjhmiNWZNQT8LU6uk9qP9t3goP9bJptdlNqMC0wBB2w9sQrxjZt835bpRSSq1LA==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "shiki": "^1.16.2", + "yaml": "^2.5.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.9.tgz", + "integrity": "sha512-Wqmx+7ezKFgtTklEq/iUhQ5uFeBDhAT6wiS2na9cFLidIpl9jpDHJy/COYh8jUZXgIRIZVQ/bPNjyrnPFoDwzg==", + "dev": true, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "typedoc": "0.26.x" + } + }, "node_modules/typescript": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", @@ -1052,6 +2430,136 @@ "node": ">=14.17" } }, + "node_modules/typical": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.2.0.tgz", + "integrity": "sha512-W1+HdVRUl8fS3MZ9ogD51GOb46xMmhAZzR0WPw5jcgIZQJVvkddYzAl4YTU6g5w33Y1iRQLdIi2/1jhi2RNL0g==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "dev": true + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { "version": "5.4.8", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", @@ -1196,6 +2704,15 @@ } } }, + "node_modules/walk-back": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.1.tgz", + "integrity": "sha512-e/FRLDVdZQWFrAzU6Hdvpm7D7m2ina833gIKLptQykRK49mmCYHLHq7UqjPDbxbKLZkTkW1rFqbengdE3sLfdw==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -1211,6 +2728,49 @@ "engines": { "node": ">=8" } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/wordwrapjs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz", + "integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index cab029c..9b50d7c 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,6 @@ "require": "./dist/cjs/index.js", "types": "./dist/index.d.ts" }, - "./tuple": { - "import": "./dist/tuple/index.js", - "require": "./dist/cjs/tuple/index.js", - "types": "./dist/tuple/index.d.ts" - }, "./go": { "import": "./dist/go/index.js", "require": "./dist/cjs/go/index.js", @@ -26,7 +21,8 @@ "build:esm": "tsc", "build:cjs": "tsc --project tsconfig.cjs.json", "test": "vitest", - "publish": "npm run build && npm publish" + "publish": "npm run build && npm publish", + "typedoc": "typedoc src" }, "files": [ "dist" @@ -52,6 +48,9 @@ "typescript" ], "devDependencies": { + "jsdoc-to-markdown": "^9.0.2", + "typedoc": "^0.26.8", + "typedoc-plugin-markdown": "^4.2.9", "typescript": "^5.6.2", "vitest": "^2.1.1" } diff --git a/src/Either.ts b/src/Either.ts index e74c049..4f4c7ca 100644 --- a/src/Either.ts +++ b/src/Either.ts @@ -6,11 +6,15 @@ * @template T The type of the result value. */ export type Either = - | { + | ({ error: Error result: undefined - } - | { + } & [Error, undefined]) + | ({ result: T error: undefined - } + } & [undefined, T]) + +// Note this array interface is undesireable, we would much rather use just an itterator here but TS doesn't yet support that well enough +// So it has an array interface and proxies array methods. +// See the utils `makeEither` for more information. \ No newline at end of file diff --git a/src/go/Either.ts b/src/go/Either.ts index c3ef383..22dc28b 100644 --- a/src/go/Either.ts +++ b/src/go/Either.ts @@ -1,12 +1,20 @@ /** - * Either type represents a tuple that encapsulates a successful result or an Error. - * - * `[undefined, Error]` represents a failed result. - * `[T, undefined]` represents a successful result. - * + * Either type represents a data structure that encapsulates a successful result or an Error. * It wraps the result of a Promise in an object, making it easier to handle errors by returning - * an array that either contains a 'result' value of type T (if successful), or an 'error' of type Error. + * an object that either contains a 'result' value of type T (if successful), or an 'error' of type Error. * * @template T The type of the result value. */ -export type Either = [undefined, Error] | [T, undefined] +export type Either = + | ({ + error: Error + result: undefined + } & [undefined, Error]) + | ({ + result: T + error: undefined + } & [T, undefined]) + +// Note this array interface is undesireable, we would much rather use just an itterator here but TS doesn't yet support that well enough +// So it has an array interface and proxies array methods. +// See the utils `makeEither` for more information. \ No newline at end of file diff --git a/src/go/makeMightFail.ts b/src/go/makeMightFail.ts index 80871fe..40538f3 100644 --- a/src/go/makeMightFail.ts +++ b/src/go/makeMightFail.ts @@ -14,7 +14,7 @@ type UnwrapPromise = T extends Promise ? U : T * returns a Promise that resolves with an Either. This allows for the handling of both resolved values and * errors in a consistent, functional way. * - * @export + * @template T The function type that returns a Promise. * @param {T} func - The async function to be wrapped. This function should return a Promise. * @return {Function} A new function that, when called, returns a Promise that resolves with an Either tuple. @@ -55,7 +55,7 @@ export function makeMightFail Promise>( * if it executes successfully as the first element and undefined as the second, or undefined as the first element * and an Error as the second if the function throws. * - * @export + * @template T The function type that might throw an error. * @param {T} func - The function to be wrapped. This function might throw an exception. * @return {Function} A new function that, when called, returns an Either tuple with either a result or an error. diff --git a/src/go/mightFail.ts b/src/go/mightFail.ts index dc84a8d..7a20dff 100644 --- a/src/go/mightFail.ts +++ b/src/go/mightFail.ts @@ -1,11 +1,14 @@ import standard from "../index" import { type Either } from "./Either" -import { makeProxyHandler } from "../utils" -import { MightFail, MightFailFunction, NonUndefined } from "../utils.type" +import { createEither } from "../utils/createEither" +import { makeProxyHandler } from "../utils/staticMethodsProxy" +import { MightFail, MightFailFunction, NonUndefined } from "../utils/utils.type" const mightFailFunction: MightFailFunction<"go"> = async function (promise: Promise) { const { result, error } = await standard.mightFailFunction(promise) - return error ? [undefined, error] : [result, undefined] + return error + ? createEither({ result: undefined, error }, "go") + : createEither({ result, error: undefined }, "go") } /** @@ -14,7 +17,7 @@ const mightFailFunction: MightFailFunction<"go"> = async function (promise: P * either contains the resolved value of type T as the first element and undefined as the second if the promise * resolves successfully, or undefined as the first element and an Error as the second if the promise is rejected. * - * @export + * @template T The type of the result value. * @param {Promise} promise - The promise to be wrapped in an Either. This is an asynchronous operation that * should resolve with a value of type T or reject with an Error. @@ -42,7 +45,7 @@ const mightFailFunction: MightFailFunction<"go"> = async function (promise: P */ export const mightFail: MightFail<"go"> = new Proxy( mightFailFunction, - makeProxyHandler(mightFailFunction) + makeProxyHandler(mightFailFunction), ) as MightFail<"go"> /** @@ -51,7 +54,7 @@ export const mightFail: MightFail<"go"> = new Proxy( * It returns an Either tuple that either contains the value of type T as the first element and undefined as the second * if the function succeeds, or undefined as the first element and an Error as the second if the function throws an error. * - * @export + * @template T The type of the result value. * @param {() => T} func - A wrapper function that is expected to invoke the throwing function. * That function should return a value of type T or throw an error. @@ -69,10 +72,11 @@ export const mightFail: MightFail<"go"> = new Proxy( */ export function mightFailSync(func: () => T): Either { const { result, error } = standard.mightFailSync(func) - return error ? [undefined, error] : [result, undefined] + return error + ? createEither({ result: undefined, error }, "go") + : createEither({ result, error: undefined }, "go") } - /** * A pure constructor function that takes a non-null value and returns an Either object with the value as the result and undefined as the error. * @@ -81,7 +85,7 @@ export function mightFailSync(func: () => T): Either { */ export function Might(result: NonUndefined): Either { const standardMight = standard.Might(result) - return [standardMight.result as T, undefined] + return createEither({ result: standardMight.result as T, error: undefined }, "go") } /** @@ -94,5 +98,5 @@ export function Might(result: NonUndefined): Either { */ export function Fail(error: unknown): Either { const standardFail = standard.Fail(error) - return [undefined, standardFail.error] + return createEither({ result: undefined, error: standardFail.error }, "go") } diff --git a/src/makeMightFail.ts b/src/makeMightFail.ts index f4eb47b..3c2d4f4 100644 --- a/src/makeMightFail.ts +++ b/src/makeMightFail.ts @@ -14,7 +14,7 @@ type UnwrapPromise = T extends Promise ? U : T * returns a Promise that resolves with an Either. This allows for the handling of both resolved values and * errors in a consistent, functional way. * - * @export + * @template T The function type that returns a Promise. * @param {T} func - The async function to be wrapped. This function should return a Promise. * @return {Function} A new function that, when called, returns a Promise that resolves with an Either object. @@ -53,7 +53,7 @@ export function makeMightFail Promise>( * instead of throwing, returns an Either object. This object contains either a 'result' * with the value returned by the function if it executes successfully, or an 'error' if the function throws. * - * @export + * @template T The function type that might throw an error. * @param {T} func - The function to be wrapped. This function might throw an exception. * @return {Function} A new function that, when called, returns an Either object with either a 'result' or an 'error'. diff --git a/src/mightFail.ts b/src/mightFail.ts index 2d202ad..23d75b1 100644 --- a/src/mightFail.ts +++ b/src/mightFail.ts @@ -1,16 +1,18 @@ import { type Either } from "./Either" -import { handleError, makeProxyHandler } from "./utils" -import { MightFail, MightFailFunction, NonUndefined } from "./utils.type" +import { makeProxyHandler } from "./utils/staticMethodsProxy" +import { handleError } from "./utils/errors" +import { createEither } from "./utils/createEither" +import { MightFail, MightFailFunction, NonUndefined } from "./utils/utils.type" export const mightFailFunction: MightFailFunction<"standard"> = async function ( promise: Promise ): Promise> { try { const result = await promise - return { error: undefined, result } as Either + return createEither({ result, error: undefined }) } catch (err) { const error = handleError(err) - return { error, result: undefined } + return createEither({ error, result: undefined }) } } @@ -20,13 +22,12 @@ export const mightFailFunction: MightFailFunction<"standard"> = async function < * either contains a 'result' of type T if the promise resolves successfully, or an 'error' of type Error * if the promise is rejected. * - * @export * @template T The type of the result value. * @param {Promise} promise - The promise to be wrapped in an Either. This is an asynchronous operation that * should resolve with a value of type T or reject with an Error. - * @return {Promise>} A Promise that resolves with an Either. This Either is a Success with + * @return {Promise>} A Promise that resolves with an Either. This Either is a `Success` with * the 'result' property set to the value resolved by the promise if successful, and 'error' as undefined. - * In case of failure, it's a Failure with 'result' as undefined and 'error' of type Error. `error` will **always** be an instance of Error. + * In case of failure, it's a `Failure` with 'result' as undefined and 'error' of type Error. `error` will **always** be an instance of Error. * * @example * // Example of wrapping an async function that might fail: @@ -57,13 +58,12 @@ export const mightFail: MightFail<"standard"> = new Proxy( * It returns an object that either contains a 'result' of type T if the function succeeds, * or an 'error' of type Error if the function throws an error. * - * @export - * @template T The type of the result value. + * @template T The type of the result value.◊ * @param {() => T} func - A wrapper function that is expected to invoke the throwing function. * That function should return a value of type T or throw an error. - * @return {Either} An object that is either a Success with the result property set to the value returned by `func`, - * or a Failure with the error property set to the caught error. Success has a 'result' of type T - * and 'error' as null. Failure has 'result' as null and 'error' of type Error. + * @return {Either} An object that is either a `Success` with the result property set to the value returned by `func`, + * or a `Failure` with the error property set to the caught error. `Success` has a 'result' of type T + * and 'error' as null. `Failure` has 'result' as null and 'error' of type Error. * @example * // Example of wrapping a synchronous function that might throw an error: * const {error, result} = mightFailSync(() => JSON.parse("")); @@ -74,36 +74,33 @@ export const mightFail: MightFail<"standard"> = new Proxy( * } * console.log('Parsed object:', result); */ - -export function mightFailSync(func: () => T): Either { +export const mightFailSync = function mightFailSync(func: () => T): Either { try { const result = func() - return { error: undefined, result } + return createEither({ error: undefined, result }) } catch (err) { const error = handleError(err) - return { error, result: undefined } + return createEither({ error, result: undefined }) } } - /** - * A pure constructor function that takes a non-null value and returns an Either object with the value as the result and undefined as the error. + * A pure constructor function that takes a non-null value and returns an `Either` object with the value as the result and undefined as the error. * * @param result - * @constructor */ -export function Might(result: NonUndefined): Either { - return { result, error: undefined } +export const Might = function Might(result: NonUndefined): Either { + return createEither({ result, error: undefined }) } /** - * A constructor function that takes an error and returns an Either object with undefined as the result and the error as the error. + * A constructor function that takes an error and returns an `Either` object with undefined as the result and the error as the error. * * The error will **always** be an instance of Error. * * @param error - * @constructor */ -export function Fail(error: unknown): Either { - return { result: undefined, error: handleError(error) } +export const Fail = function Fail(error: unknown): Either { + return createEither({ result: undefined, error: handleError(error) }) } + diff --git a/src/tuple/Either.ts b/src/tuple/Either.ts deleted file mode 100644 index 9044d37..0000000 --- a/src/tuple/Either.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Either type represents a tuple that encapsulates a successful result or an Error. - * - * `[Error, undefined]` represents a failed result. - * `[undefined, T]` represents a successful result. - * - * It wraps the result of a Promise in an object, making it easier to handle errors by returning - * an array that either contains a 'result' value of type T (if successful), or an 'error' of type Error. - * - * @template T The type of the result value. - */ -export type Either = [Error, undefined] | [undefined, T] diff --git a/src/tuple/index.ts b/src/tuple/index.ts deleted file mode 100644 index 5c86b4d..0000000 --- a/src/tuple/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @module - * - * This module contains the interface to use the result of mightFail as an error-first tuple. - * - * This mimics the behaviour of golang. - * - * If you want to use error-first style, use the `/tuple` module. - * -+ * @example -+ * ```ts -+ * import { mightFail } from "@might/fail/tuple"; -+ * -+ * const [result, error] = await mightFail(promise); -+ * ``` - */ - -import { type Either } from "./Either" -import { mightFail, mightFailSync, Might, Fail } from "./mightFail" -import { makeMightFail, makeMightFailSync } from "./makeMightFail" - -export { Either, mightFail, makeMightFail, mightFailSync, makeMightFailSync, Might, Fail } -export default { mightFail, makeMightFail, mightFailSync, makeMightFailSync, Might, Fail } diff --git a/src/tuple/makeMightFail.ts b/src/tuple/makeMightFail.ts deleted file mode 100644 index af8e481..0000000 --- a/src/tuple/makeMightFail.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { type Either } from "./Either" -import { mightFail, mightFailSync } from "./mightFail" - -/** - * Utility type that unwraps a Promise type. If T is a Promise, it extracts the type the Promise resolves to, - * providing direct access to the underlying value type. - * - * @template T The type to be unwrapped if it's a Promise. - */ -type UnwrapPromise = T extends Promise ? U : T - -/** - * Wraps a promise-returning function in another function that instead of returning a Promise directly, - * returns a Promise that resolves with an Either tuple. This allows for the handling of both resolved values and - * errors in a consistent, functional way. - * - * @export - * @template T The function type that returns a Promise. - * @param {T} func - The async function to be wrapped. This function should return a Promise. - * @return {Function} A new function that, when called, returns a Promise that resolves with an Either tuple. - * The Either tuple is [undefined, T] where T is the resolved value of the original Promise if successful, - * or [Error, undefined] if the Promise was rejected. - * - * @example - * // Example of wrapping an async function that might fail: - * async function fetchData(url: string): Promise { - * const response = await fetch(url); - * if (!response.ok) { - * throw new Error('Network response was not ok'); - * } - * return response.text(); - * } - * - * const safeFetchData = makeMightFail(fetchData); - * const [error, result] = await safeFetchData('https://example.com'); - * - * if (error) { - * console.error('Fetching failed:', error.message); - * return; - * } - * console.log('Fetched data:', result); - */ -export function makeMightFail Promise>( - func: T -): (...funcArgs: Parameters) => Promise>>> { - return async (...args: Parameters) => { - const promise = func(...args) - return mightFail(promise) - } -} - -/** - * Wraps a synchronous function that might throw an exception in another function that, - * instead of throwing, returns an Either tuple. This tuple contains either undefined as the first element - * and the value returned by the function as the second if it executes successfully, - * or an Error as the first element and undefined as the second if the function throws. - * - * @export - * @template T The function type that might throw an error. - * @param {T} func - The function to be wrapped. This function might throw an exception. - * @return {Function} A new function that, when called, returns an Either tuple with either [undefined, T] or [Error, undefined]. - * - * @example - * // Example of wrapping a synchronous function that might throw an error: - * function parseJSON(jsonString: string) { - * return JSON.parse(jsonString); // This might throw - * } - * - * const safeParseJSON = makeMightFailSync(parseJSON); - * const [error, result] = safeParseJSON('{"valid": "json"}'); - * - * if (error) { - * console.error('Parsing failed:', error); - * return; - * } - * console.log('Parsed object:', result); - */ -export function makeMightFailSync any>( - func: T -): (...funcArgs: Parameters) => Either> { - return (...args: Parameters) => { - const throwingFunction = () => func(...args) - return mightFailSync(throwingFunction) - } -} diff --git a/src/tuple/mightFail.ts b/src/tuple/mightFail.ts deleted file mode 100644 index 0f8595b..0000000 --- a/src/tuple/mightFail.ts +++ /dev/null @@ -1,99 +0,0 @@ -import standard from "../index" -import { type Either } from "./Either" -import { makeProxyHandler } from "../utils" -import { MightFail, MightFailFunction, NonUndefined } from "../utils.type" - -const mightFailFunction: MightFailFunction<"tuple"> = async function (promise: Promise) { - const { result, error } = await standard.mightFailFunction(promise) - return error ? [error, undefined] : [undefined, result] -} - -/** - * Wraps a promise in an Either tuple to safely handle both its resolution and rejection. This function - * takes a Promise of type T and returns a Promise which resolves with an Either tuple. This tuple - * either contains an Error as the first element and undefined as the second if the promise is rejected, - * or undefined as the first element and a 'result' of type T as the second if the promise resolves successfully. - * - * @export - * @template T The type of the result value. - * @param {Promise} promise - The promise to be wrapped in an Either. This is an asynchronous operation that - * should resolve with a value of type T or reject with an Error. - * @return {Promise>} A Promise that resolves with an Either tuple. This Either is [undefined, T] with - * the second element set to the value resolved by the promise if successful. In case of failure, it's [Error, undefined] - * with the first element being the Error. The Error will always be an instance of Error. - * - * @example - * // Example of wrapping an async function that might fail: - * async function fetchData(url: string): Promise { - * const response = await fetch(url); - * if (!response.ok) { - * throw new Error('Network response was not ok'); - * } - * return response.text(); - * } - * - * const [error, result] = await mightFail(fetchData('https://example.com')); - * - * if (error) { - * console.error('Fetching failed:', error.message); - * return; - * } - * console.log('Fetched data:', result); - */ -export const mightFail: MightFail<"tuple"> = new Proxy( - mightFailFunction, - makeProxyHandler(mightFailFunction) -) as MightFail<"tuple"> - -/** - * Wraps a synchronous function in an Either tuple to safely handle exceptions. This function - * executes a provided function that returns a value of type T, capturing any thrown errors. - * It returns a tuple that either contains an Error as the first element and undefined as the second - * if the function throws, or undefined as the first element and a value of type T as the second - * if the function succeeds. - * - * @export - * @template T The type of the result value. - * @param {() => T} func - A wrapper function that is expected to invoke the throwing function. - * That function should return a value of type T or throw an error. - * @return {Either} A tuple that is either [undefined, T] with the second element set to the value returned by `func`, - * or [Error, undefined] with the first element set to the caught error. - * @example - * // Example of wrapping a synchronous function that might throw an error: - * const [error, result] = mightFailSync(() => JSON.parse("")); - * - * if (error) { - * console.error('Parsing failed:', error); - * return; - * } - * console.log('Parsed object:', result); - */ -export function mightFailSync(func: () => T): Either { - const { result, error } = standard.mightFailSync(func) - return error ? [error, undefined] : [undefined, result] -} - - -/** - * A pure constructor function that takes a non-null value and returns an Either object with the value as the result and undefined as the error. - * - * @param result - * @constructor - */ -export function Might(result: NonUndefined): Either { - const standardMight = standard.Might(result) - return [undefined, standardMight.result as T] -} - -/** - * A constructor function that takes an error and returns an Either object with undefined as the result and the error as the error. - * - * The error will **always** be an instance of Error. - * - * @param error - * @constructor - */ -export function Fail(error: unknown): Either { - const standardFail = standard.Fail(error) - return [standardFail.error, undefined] -} diff --git a/src/utils.ts b/src/utils.ts deleted file mode 100644 index 3b2f8c8..0000000 --- a/src/utils.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { EitherMode, MightFailFunction } from "./utils.type" - -export function handleError(error: unknown): Error { - if (error instanceof Error) { - return error - } - if (typeof error === "string") { - return createErrorWithoutMightFailStackTraces(error) - } - if (typeof error === "object" && error !== null) { - if ("message" in error && typeof error.message === "string") { - return createErrorWithoutMightFailStackTraces(error.message) - } - return createErrorWithoutMightFailStackTraces(error as any) - } - return createErrorWithoutMightFailStackTraces("Unknown error") -} - -function createErrorWithoutMightFailStackTraces(message: any): Error { - const error = new Error(message) - - const stack = error.stack?.split("\n") - stack?.splice(1, 3) - error.stack = stack?.join("\n") - - return error -} - -export const makeProxyHandler = >( - mightFailFunction: TMightFailFunction -) => ({ - get(_: TMightFailFunction, property: string) { - if (Object.getOwnPropertyDescriptor(Promise, property) === undefined) { - return mightFailFunction(Promise.reject(new Error(`property ${property} not found on Promise`))) - } - - const value = (Promise as any)[property] - - if (typeof value !== "function") { - return mightFailFunction(Promise.reject(new Error(`property ${property} is not a Promise method`))) - } - - return function (...args: any[]) { - const promise = value.apply(Promise, args) - return mightFailFunction(promise) - } - }, -}) diff --git a/src/utils/createEither.ts b/src/utils/createEither.ts new file mode 100644 index 0000000..07a135c --- /dev/null +++ b/src/utils/createEither.ts @@ -0,0 +1,76 @@ +import { EitherMode } from "./utils.type" +import type { Either as StandardEither } from "../Either" +import type { Either as GoEither } from "../go/Either" + + +// This is not how we intended the tuple feature to work but this is the only way we could currently get TypeScript to play nice +// this really should just be an interator on the either object, but it's much more complicated because of TS. +// All the details are in this PR https://github.com/meech-ward/might-fail/pull/7#issuecomment-2395122593 +// hopefully we can change this with a future version of TS. + +export const createEither = ( + { + result, + error, + }: + | { + error: Error + result: undefined + } + | { + error: undefined + result: T + }, + eitherMode: EitherMode = "standard", +): TEitherMode extends "standard" ? StandardEither : GoEither => { + if (error) { + const array = eitherMode === "standard" ? [error, undefined] : [undefined, error] + const obj = {} as any + obj.error = error + obj.result = undefined + return createArrayProxy(obj, array) + } + const array = eitherMode === "standard" ? [undefined, result] : [result, undefined] + const obj = {} as any + obj.error = undefined + obj.result = result + return createArrayProxy(obj, array) +} + +const createArrayProxy = (obj: any, array: (undefined | Error | T)[]) => { + // Proxy to intercept array methods and properties + return new Proxy(obj, { + get(target, prop, receiver) { + // If the property exists on the object itself, return it + if (prop in target) { + return Reflect.get(target, prop, receiver) + } + + // If the property exists on the internal array, proxy it + if (prop in array) { + const value = (array as any)[prop] // TypeScript array typing here + if (typeof value === "function") { + // Proxy array methods + return function (...args: any[]) { + return value.apply(array, args) + } + } else { + // Return array properties (like length) + return value + } + } + + // Handle the iterator separately + if (prop === Symbol.iterator) { + const originalIterator = array[Symbol.iterator]() + return function* () { + for (let item of originalIterator) { + yield item + } + } + } + + return undefined + }, + }) +} diff --git a/src/utils/errors.ts b/src/utils/errors.ts new file mode 100644 index 0000000..074f7fa --- /dev/null +++ b/src/utils/errors.ts @@ -0,0 +1,25 @@ +export function handleError(error: unknown): Error { + if (error instanceof Error) { + return error + } + if (typeof error === "string") { + return createErrorWithoutMightFailStackTraces(error) + } + if (typeof error === "object" && error !== null) { + if ("message" in error && typeof error.message === "string") { + return createErrorWithoutMightFailStackTraces(error.message) + } + return createErrorWithoutMightFailStackTraces(error as any) + } + return createErrorWithoutMightFailStackTraces("Unknown error") +} + +function createErrorWithoutMightFailStackTraces(message: any): Error { + const error = new Error(message) + + const stack = error.stack?.split("\n") + stack?.splice(1, 3) + error.stack = stack?.join("\n") + + return error +} \ No newline at end of file diff --git a/src/utils/staticMethodsProxy.ts b/src/utils/staticMethodsProxy.ts new file mode 100644 index 0000000..c2bb01b --- /dev/null +++ b/src/utils/staticMethodsProxy.ts @@ -0,0 +1,22 @@ +import { EitherMode, MightFailFunction } from "./utils.type" + +export const makeProxyHandler = >( + mightFailFunction: TMightFailFunction, +) => ({ + get(_: TMightFailFunction, property: string) { + if (Object.getOwnPropertyDescriptor(Promise, property) === undefined) { + return mightFailFunction(Promise.reject(new Error(`property ${property} not found on Promise`))) + } + + const value = (Promise as any)[property] + + if (typeof value !== "function") { + return mightFailFunction(Promise.reject(new Error(`property ${property} is not a Promise method`))) + } + + return function (...args: any[]) { + const promise = value.apply(Promise, args) + return mightFailFunction(promise) + } + }, +}) diff --git a/src/utils.type.ts b/src/utils/utils.type.ts similarity index 79% rename from src/utils.type.ts rename to src/utils/utils.type.ts index ce4d33b..ba991cf 100644 --- a/src/utils.type.ts +++ b/src/utils/utils.type.ts @@ -1,18 +1,15 @@ -import type { Either as StandardEither } from "./Either" -import type { Either as TupleEither } from "./tuple" -import type { Either as GoEither } from "./go" +import type { Either as StandardEither } from "../Either" +import type { Either as GoEither } from "../go/Either" -export type EitherMode = "standard" | "tuple" | "go" | "any" +export type EitherMode = "standard" | "go" | "any" -export type AnyEither = StandardEither | TupleEither | GoEither +export type AnyEither = StandardEither | GoEither export type MightFailFunction = ( promise: Promise ) => Promise< TEitherMode extends "standard" ? StandardEither - : TEitherMode extends "tuple" - ? TupleEither : TEitherMode extends "go" ? GoEither : AnyEither @@ -36,7 +33,7 @@ export type MightFail< export interface PromiseStaticMethods { /** * Wraps a Promise.all call in a mightFail function. - * @params values + * @param values - An iterable of promises * @template T The type of the resolved values * @return {Promise} - Promise>> */ @@ -45,8 +42,6 @@ export interface PromiseStaticMethods { ): Promise< TEitherMode extends "standard" ? Awaited> - : TEitherMode extends "tuple" - ? Awaited> : TEitherMode extends "go" ? Awaited> : Awaited> @@ -54,7 +49,7 @@ export interface PromiseStaticMethods { /** * Wraps a Promise.all call in a mightFail function. - * @params values + * @param values - An array of promises * @template T The type of the resolved values * @return {Promise} - Promise; }>> */ @@ -63,8 +58,6 @@ export interface PromiseStaticMethods { ): Promise< TEitherMode extends "standard" ? StandardEither<{ -readonly [P in keyof T]: Awaited }> - : TEitherMode extends "tuple" - ? TupleEither<{ -readonly [P in keyof T]: Awaited }> : TEitherMode extends "go" ? GoEither<{ -readonly [P in keyof T]: Awaited }> : AnyEither<{ -readonly [P in keyof T]: Awaited }> @@ -73,7 +66,7 @@ export interface PromiseStaticMethods { /** * Wraps a Promise.race call in a mightFail function. * - * @params values - An iterable of promises + * @param values - An array of promises * @template T The type of the resolved values * @return {Promise} - Promise>> */ @@ -82,8 +75,6 @@ export interface PromiseStaticMethods { ): Promise< TEitherMode extends "standard" ? Awaited> - : TEitherMode extends "tuple" - ? Awaited> : TEitherMode extends "go" ? Awaited> : Awaited> @@ -91,7 +82,7 @@ export interface PromiseStaticMethods { /** * Wraps a Promise.race call in a mightFail function. - * @params values + * @param values - An array of promises * @template T The type of the resolved values * @return {Promise} - Promise>> */ @@ -100,8 +91,6 @@ export interface PromiseStaticMethods { ): Promise< TEitherMode extends "standard" ? Awaited> - : TEitherMode extends "tuple" - ? Awaited> : TEitherMode extends "go" ? Awaited> : Awaited> @@ -109,7 +98,7 @@ export interface PromiseStaticMethods { /** * Wraps a Promise.allSettled call in a mightFail function. - * @params values + * @param values - An array of promises * @template T The type of the resolved values * @return {Promise} - Promise>}>> */ @@ -118,8 +107,6 @@ export interface PromiseStaticMethods { ): Promise< TEitherMode extends "standard" ? StandardEither<{ -readonly [P in keyof T]: PromiseSettledResult> }> - : TEitherMode extends "tuple" - ? TupleEither<{ -readonly [P in keyof T]: PromiseSettledResult> }> : TEitherMode extends "go" ? GoEither<{ -readonly [P in keyof T]: PromiseSettledResult> }> : AnyEither<{ -readonly [P in keyof T]: PromiseSettledResult> }> @@ -127,7 +114,7 @@ export interface PromiseStaticMethods { /** * Wraps a Promise.allSettled call in a mightFail function. - * @params values + * @param values - An iterable of promises * @template T The type of the resolved values * @return {Promise} - Promise>[]>> */ @@ -136,8 +123,6 @@ export interface PromiseStaticMethods { ): Promise< TEitherMode extends "standard" ? StandardEither>[]> - : TEitherMode extends "tuple" - ? TupleEither>[]> : TEitherMode extends "go" ? GoEither>[]> : AnyEither>[]> @@ -146,7 +131,7 @@ export interface PromiseStaticMethods { /** * Wraps a Promise.any call in a mightFail function. * - * @params values + * @param values - An array of promises * @template T The type of the resolved values * @return {Promise} - Promise>> */ @@ -155,8 +140,6 @@ export interface PromiseStaticMethods { ): Promise< TEitherMode extends "standard" ? StandardEither> - : TEitherMode extends "tuple" - ? TupleEither> : TEitherMode extends "go" ? GoEither> : AnyEither> @@ -165,7 +148,7 @@ export interface PromiseStaticMethods { /** * Wraps a Promise.any call in a mightFail function. * - * @params values + * @param values - An iterable of promises * @template T The type of the resolved values * @return {Promise} - Promise>> */ @@ -174,8 +157,6 @@ export interface PromiseStaticMethods { ): Promise< TEitherMode extends "standard" ? StandardEither> - : TEitherMode extends "tuple" - ? TupleEither> : TEitherMode extends "go" ? GoEither> : AnyEither> diff --git a/test/go/mightFail.test.ts b/test/go/mightFail.test.ts index 7deacd9..82c6229 100644 --- a/test/go/mightFail.test.ts +++ b/test/go/mightFail.test.ts @@ -127,21 +127,24 @@ describe("promise concurrent method wrappers", () => { describe("Either factories (Might & Fail)", () => { describe("Might", () => { it("should return an Either with the value as the result and undefined as the error", () => { - const result = Might(5) - expect(result).toEqual([5, undefined]) + const [result, error] = Might(5) + expect(result).toEqual(5) + expect(error).toEqual(undefined) }) }) describe("Fail", () => { it("should return an Either with undefined as the result and the error as the error", () => { const error = new Error("error") - const result = Fail(error) - expect(result).toEqual([undefined, error]) + const [failResult, failError] = Fail(error) + expect(failResult).toEqual(undefined) + expect(failError).toEqual(error) }) it("should return an Either with undefined as the result and the error must be an instance of Error", () => { const error = "error" - const result = Fail(error) - expect(result).toEqual([undefined, new Error(error)]) + const [failResult, failError] = Fail(error) + expect(failResult).toEqual(undefined) + expect(failError).toEqual(new Error(error)) }) }) }) diff --git a/test/tuple/makeMightFail.test.ts b/test/tuple/makeMightFail.test.ts index a08c5b2..b9ecc99 100644 --- a/test/tuple/makeMightFail.test.ts +++ b/test/tuple/makeMightFail.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "vitest" -import { makeMightFail } from "../../src/tuple/index" +import { makeMightFail } from "../../src/index" test("success returns the response", async () => { const resolve = (value: { message: string }) => Promise.resolve(value) diff --git a/test/tuple/makeMightFailSync.test.ts b/test/tuple/makeMightFailSync.test.ts index 32b72a4..3c2545d 100644 --- a/test/tuple/makeMightFailSync.test.ts +++ b/test/tuple/makeMightFailSync.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "vitest" -import { makeMightFailSync } from "../../src/tuple/index" +import { makeMightFailSync } from "../../src/index" function somethingThatThrows(input: string) { if (!input) { diff --git a/test/tuple/mightFail.test.ts b/test/tuple/mightFail.test.ts index bd2437d..7ec3f75 100644 --- a/test/tuple/mightFail.test.ts +++ b/test/tuple/mightFail.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, test } from "vitest" -import { mightFail, Might, Fail } from "../../src/tuple/index" +import { mightFail, Might, Fail } from "../../src/index" test("success returns the response", async () => { const [error, result] = await mightFail(Promise.resolve("success")) @@ -127,21 +127,24 @@ describe("promise concurrent method wrappers", () => { describe("Either factories (Might & Fail)", () => { describe("Might", () => { it("should return an Either with the value as the result and undefined as the error", () => { - const result = Might(5) - expect(result).toEqual([undefined, 5]) + const [errResult, resResult] = Might(5) + expect(errResult).toEqual(undefined) + expect(resResult).toEqual(5) }) }) describe("Fail", () => { it("should return an Either with undefined as the result and the error as the error", () => { const error = new Error("error") - const result = Fail(error) - expect(result).toEqual([error, undefined]) + const [errResult, resResult] = Fail(error) + expect(errResult).toEqual(error) + expect(resResult).toEqual(undefined) }) it("should return an Either with undefined as the result and the error must be an instance of Error", () => { const error = "error" - const result = Fail(error) - expect(result).toEqual([new Error(error), undefined]) + const [errResult, resResult] = Fail(error) + expect(errResult).toEqual(new Error(error)) + expect(resResult).toEqual(undefined) }) }) }) diff --git a/test/tuple/mightFailSync.test.ts b/test/tuple/mightFailSync.test.ts index a24a91c..efda2a1 100644 --- a/test/tuple/mightFailSync.test.ts +++ b/test/tuple/mightFailSync.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "vitest" -import { mightFailSync } from "../../src/tuple/index" +import { mightFailSync } from "../../src/index" function somethingThatThrows(input: string) { if (!input) { diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..6d0e835 --- /dev/null +++ b/typedoc.json @@ -0,0 +1,25 @@ +{ + "plugin": [ + "typedoc-plugin-markdown" + ], + "out": "./docs/content/jsdocs", + "outputFileStrategy": "members", + "hidePageHeader": true, + "hideBreadcrumbs": true, + "useCodeBlocks": true, + "expandObjects": true, + "expandParameters": true, + "parametersFormat": "table", + "interfacePropertiesFormat": "table", + "classPropertiesFormat": "table", + "enumMembersFormat": "table", + "typeDeclarationFormat": "table", + "propertyMembersFormat": "table", + "publicPath": "https://mightfail.dev", + "sanitizeComments": true, + "anchorPrefix": "markdown-header", + "fileExtension": ".mdx", + "entryFileName": "index", + "readme": "none", + "disableSources": true +} \ No newline at end of file