diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 660156e..457f3fb 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -9,18 +9,21 @@ on: - master jobs: - build: + publish-docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - - run: npm ci - - run: npm test + registry-url: https://registry.npmjs.org/ + - run: npm run doc + - name: Deploy to Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: docs publish-npm: - needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index c6bba59..837cdf0 100644 --- a/.gitignore +++ b/.gitignore @@ -91,6 +91,9 @@ out .nuxt dist +# Typedoc generated documentation +docs + # Gatsby files .cache/ # Comment in the public line in if your project uses Gatsby and not Next.js diff --git a/package-lock.json b/package-lock.json index e005d64..4fbbae4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "jest": "^30.0.5", "rimraf": "^6.0.1", "ts-jest": "^29.4.1", + "typedoc": "^0.28.11", "typescript": "^5.9.2" } }, @@ -561,6 +562,20 @@ "tslib": "^2.4.0" } }, + "node_modules/@gerrit0/mini-shiki": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.11.0.tgz", + "integrity": "sha512-ooCDMAOKv71O7MszbXjSQGcI6K5T6NKlemQZOBHLq7Sv/oXCRfYbZ7UgbzFdl20lSXju6Juds4I3y30R6rHA4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-oniguruma": "^3.11.0", + "@shikijs/langs": "^3.11.0", + "@shikijs/themes": "^3.11.0", + "@shikijs/types": "^3.11.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1109,6 +1124,55 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.12.0.tgz", + "integrity": "sha512-IfDl3oXPbJ/Jr2K8mLeQVpnF+FxjAc7ZPDkgr38uEw/Bg3u638neSrpwqOTnTHXt1aU0Fk1/J+/RBdst1kVqLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.12.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.12.0.tgz", + "integrity": "sha512-HIca0daEySJ8zuy9bdrtcBPhcYBo8wR1dyHk1vKrOuwDsITtZuQeGhEkcEfWc6IDyTcom7LRFCH6P7ljGSCEiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.12.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.12.0.tgz", + "integrity": "sha512-/lxvQxSI5s4qZLV/AuFaA4Wt61t/0Oka/P9Lmpr1UV+HydNCczO3DMHOC/CsXCCpbv4Zq8sMD0cDa7mvaVoj0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.12.0" + } + }, + "node_modules/@shikijs/types": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.12.0.tgz", + "integrity": "sha512-jsFzm8hCeTINC3OCmTZdhR9DOl/foJWplH2Px0bTi4m8z59fnsueLsweX82oGcjRQ7mfQAluQYKGoH2VzsWY4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, "node_modules/@sinclair/typebox": { "version": "0.34.40", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.40.tgz", @@ -1192,6 +1256,16 @@ "@babel/types": "^7.28.2" } }, + "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, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -1261,6 +1335,13 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT" + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -2160,6 +2241,19 @@ "dev": true, "license": "MIT" }, + "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, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3518,6 +3612,16 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -3548,6 +3652,13 @@ "yallist": "^3.0.2" } }, + "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, + "license": "MIT" + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -3607,6 +3718,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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, + "license": "MIT", + "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/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, + "license": "Python-2.0" + }, + "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, + "license": "MIT" + }, "node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", @@ -4094,6 +4237,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", @@ -4845,6 +4998,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedoc": { + "version": "0.28.11", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.11.tgz", + "integrity": "sha512-1FqgrrUYGNuE3kImAiEDgAVVVacxdO4ZVTKbiOVDGkoeSB4sNwQaDpa8mta+Lw5TEzBFmGXzsg0I1NLRIoaSFw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@gerrit0/mini-shiki": "^3.9.0", + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "yaml": "^2.8.0" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 18", + "pnpm": ">= 10" + }, + "peerDependencies": { + "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x" + } + }, "node_modules/types-json": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/types-json/-/types-json-1.2.2.tgz", @@ -4866,6 +5043,13 @@ "node": ">=14.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, + "license": "MIT" + }, "node_modules/uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", @@ -5110,6 +5294,19 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index 3a1e177..b46cb4b 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ }, "scripts": { "test": "jest", - "build": "rimraf dist && tsc" + "build": "rimraf dist && tsc", + "doc": "typedoc" }, "keywords": [ "rust", @@ -31,6 +32,7 @@ "jest": "^30.0.5", "rimraf": "^6.0.1", "ts-jest": "^29.4.1", + "typedoc": "^0.28.11", "typescript": "^5.9.2" } } diff --git a/src/option/index.ts b/src/option/index.ts index c88241b..e92e499 100644 --- a/src/option/index.ts +++ b/src/option/index.ts @@ -1,4 +1,4 @@ -import { err, ok, Result } from "../result"; +import { Result, result } from "../result"; enum MarkerType { Some, @@ -19,6 +19,7 @@ export class OptionIsEmptyError extends Error { * Represents an `Option` type with no value. */ export type None = { + /** @ignore */ readonly _marker: MarkerType.None; }; @@ -27,12 +28,13 @@ export type None = { */ export type Some = { readonly value: T; + /** @ignore */ readonly _marker: MarkerType.Some; }; export type SerializableOption = None | Some; -interface OptionUtils { +export interface OptionUtils { /** * Utility function to determine whether this `Option` type is a `Some` type. * @returns `true` if the `Option` is a `Some`, otherwise `false`. @@ -126,10 +128,10 @@ function buildOption(innerType: Some | None): Option { }, okOr(error) { if (this.isNone()) { - if (error instanceof Error) return err(error); - return err(new Error(error)); + if (error instanceof Error) return result.err(error); + return result.err(new Error(error)); } - return ok(this.value); + return result.ok(this.value); }, map(mapFn) { if (this.isNone()) { @@ -160,9 +162,7 @@ function buildOption(innerType: Some | None): Option { * @param option A serializable option which can be converted into JSON. * @returns An Option with all the data from the SerializableOption plus the utility functions */ -export function fromSerializableOption( - option?: SerializableOption, -): Option { +function fromSerializableOption(option?: SerializableOption): Option { if (option && option._marker === MarkerType.Some) { return some(option.value); } else { @@ -174,7 +174,7 @@ export function fromSerializableOption( * Constructs an `Option` type with no value. * @returns An `Option` type with no value. */ -export function none(): Option { +function none(): Option { return buildOption({ _marker: MarkerType.None }); } @@ -183,7 +183,7 @@ export function none(): Option { * @param value The value to store in the `Option`. * @returns An `Option` type with the provided value. */ -export function some(value: T): Option { +function some(value: T): Option { return buildOption({ value, _marker: MarkerType.Some }); } @@ -192,7 +192,7 @@ export function some(value: T): Option { * @param value The value to store in the `Option`. * @returns An `Option` type with the provided value and a marker indicating that it is a Some. */ -export function unknown(value?: T | null): Option { +function unknown(value?: T | null): Option { if (value === undefined || value === null) { return none(); } @@ -205,17 +205,15 @@ export function unknown(value?: T | null): Option { * @param input - A `SerializableOption` * @returns Whether or not the input is `None` */ -export function isNone(input: SerializableOption): input is None; +function isNone(input: SerializableOption): input is None; /** * A static helper function to check if an input is `None`. Useful if you want to check a `SerializableOption` * without re-serializing into an `Option`. * @param input - An `Option` * @returns Whether or not the input is `None` */ -export function isNone(input: Option): input is None & OptionUtils; -export function isNone( - input: Option | SerializableOption, -): input is None { +function isNone(input: Option): input is None & OptionUtils; +function isNone(input: Option | SerializableOption): input is None { return input._marker === MarkerType.None; } @@ -225,17 +223,15 @@ export function isNone( * @param input - A `SerializableOption` * @returns Whether or not the input is `Some` */ -export function isSome(input: SerializableOption): input is Some; +function isSome(input: SerializableOption): input is Some; /** * A static helper function to check if an input is `Some`. Useful if you want to check a `SerializableOption` * without re-serializing into an `Option`. * @param input - An `Option` * @returns Whether or not the input is `Some` */ -export function isSome(input: Option): input is Some & OptionUtils; -export function isSome( - input: Option | SerializableOption, -): input is Some { +function isSome(input: Option): input is Some & OptionUtils; +function isSome(input: Option | SerializableOption): input is Some { return input._marker === MarkerType.Some; } diff --git a/src/result/index.ts b/src/result/index.ts index 51cf17e..fc9b646 100644 --- a/src/result/index.ts +++ b/src/result/index.ts @@ -1,4 +1,4 @@ -import { none, Option, some } from "../option"; +import { option, Option } from "../option"; /** * Represents an unknown error type that is not an instance of `Error` @@ -40,7 +40,7 @@ export type Failure = { readonly error: E; }; -interface ResultUtils { +export interface ResultUtils { /** * Utility function to determine if the inner type is a `Failure` * @returns `true` if the inner type is a `Failure`, otherwise `false` @@ -142,15 +142,15 @@ function buildResult( }, ok(): Option { if (this.isOk()) { - return some(this.value); + return option.some(this.value); } - return none(); + return option.none(); }, err(): Option { if (this.isError()) { - return some(this.error); + return option.some(this.error); } - return none(); + return option.none(); }, mapOk(fn: (value: T) => NewT): Result { if (this.isOk()) { @@ -173,17 +173,15 @@ function buildResult( }; } -export function err(): Result; -export function err(error: string): Result; -export function err(error: E): Result; +function err(): Result; +function err(error: string): Result; +function err(error: E): Result; /** * Constructs a `Result` type with a `Failure` inner type. * @param error The error to wrap in the `Result` * @returns A `Result` type with a `Failure` inner type */ -export function err( - error?: E | string, -): Result { +function err(error?: E | string): Result { if (!error) { return buildResult( { error: new Error() } as Failure, @@ -204,7 +202,7 @@ export function err( * @param value The value to wrap in the `Result` * @returns A `Result` type with a `Success` inner type */ -export function ok(value: T): Result { +function ok(value: T): Result { const innerType: Success = { value, }; @@ -217,7 +215,7 @@ export function ok(value: T): Result { * otherwise a `Failure` if the `Promise` rejects. * @param val The `Result, E>` to convert to a `Promise>` */ -export async function fromPromise( +async function fromPromise( val: Result, E>, ): Promise>; /** @@ -225,10 +223,10 @@ export async function fromPromise( * otherwise a `Failure` if the `Promise` rejects. * @param val The `Promise` to convert to a `Promise>` */ -export async function fromPromise( +async function fromPromise( val: Promise, ): Promise>; -export async function fromPromise( +async function fromPromise( val: Promise | Result, E>, ): Promise> { let promise: Promise;