diff --git a/README.md b/README.md index bb1d397..e24201a 100644 --- a/README.md +++ b/README.md @@ -1,261 +1,4 @@ # Katxupa **Delicious Dish for Typescript and JavaScript projects.** -In [Cape Verde](https://en.wikipedia.org/wiki/Cape_Verde) we have a saying: - -"_Put a person to work in the field and serve them anything other than [Katxupa](https://www.crumbsnatched.com/cachupa-traditional-dish-of-cape-verde/) -for breakfast, and you'll notice a decline in productivity and motivation. Therefore, give them Katxupa and spice it up on the side._" - -Just as "_Katxupa_" is an essential part of Cape Verdean culture, this library brings _functional_ elements to enhance your -productivity and developer happiness. So, consume (use) it! - -> **Katxupa**, Cape Verde’s national dish, is a flavorful stew consisting of hominy, beans, seasoned meats, and vegetables. -> Each family has its unique version, leading to delightful variations. -> One undeniable fact: there is no Cape Verdean who doesn't appreciate Katxupa ("Cachupa") — whether for breakfast, lunch, dinner, or any time, anywhere. - -## Why Katxupa -For starters, the "_K_" in **Katxupa** stands for [Kotlin](https://kotlinlang.org/), which was the primary inspiration for this library. Drawing from the -functional programming paradigm of Kotlin and its concise yet expressive syntax, Katxupa aims to bring similar benefits -to Typescript and JavaScript developers. - -### What Makes Katxupa Special? -* **Functional Delight**: _Katxupa_ introduces functional programming concepts to enhance your code's expressiveness and clarity. - -* **Kotlin-Inspired Goodness**: Leveraging lessons learned from Kotlin, _Katxupa_ provides utilities and extensions that streamline your workflow. - -* **Boosted Productivity**: Enjoy a more productive development experience with _Katxupa_'s utility classes, sequences, durations, and more. - -* **Developer Happiness**: Inspired by the joy of coding in Kotlin, Katxupa seeks to bring happiness to your TypeScript and JavaScript projects. - -### Key Features -* **Scope Functions**: _Kotlin-like_ scope functions, provides a set of functions to execute a block of code in the context of a given object: _letIt_, _runIt_, _withIt_, _apply_, and _also_. - -* **Collections Functions**: _Kotlin-like_ functions for Arrays, Maps, and Sets: Apply concise and expressive operations on collections. - -* **Sequences**: Lazy sequences with a _Kotlin-esque_ feel, providing a convenient way to work with iterable data. - -* **Duration**: A flexible and comprehensive time duration class with support for various units, offering better time handling. - -* **Optional**: A type that represents an optional value, helping to avoid null or undefined-related issues. - -* **Result and Either**: Functional constructs to handle success, errors, and alternate paths in a more expressive manner. - -* **Inspired by Cape Verde**: Infused with the spirit of [Cape Verde](https://en.wikipedia.org/wiki/Cape_Verde) and its cherished dish **Katxupa**, this library aims to add flavor to your coding experience. - -### Get a Taste of Katxupa -Explore the documentation and see how Katxupa can bring a delightful touch to your TypeScript and JavaScript projects. -From functional programming utilities to time handling and result handling, **Katxupa** is here to make your coding journey _more enjoyable_. - -## Installation -This package is build up with simplicity in mind, brings no additional dependencies, and it's published in NPM https://www.npmjs.com/package/katxupa. - -It can be installed using your preferred package manager. - -### NPM -```shell -npm install katxupa -``` - -### PNPM -```shell -pnpm install katxupa -``` - -### YARN -```shell -yarn add katxupa -``` - -## Usage -### Scope Functions -Simply call any value with **_letIt_**, **_runIt_**, **_alsoIt_** or **_applyIt_**, and it'll be passed as the argument or the context of a scope function. - -```ts -const person = {name: "Manuel", email: "ney.br.santos@gmail.com", age: 35}; - -person.letIt(it => { - console.log(`${it.name},`); - it.age < 30 ? console.log("A Young Man") : console.log("An Old Man"); - return it.age; -}).alsoIt(it => { - console.log(`Actual Age is ${it}`); -}); -// Output: -// Manuel, -// An Old Man -// Actual Age is 35 -``` - -It also supports the use of the new [Optional Chaining Operator](https://github.com/tc39/proposal-optional-chaining), -bringing the logic of [Kotlin's Null Safe Calls](https://kotlinlang.org/docs/reference/null-safety.html) to the JavaScript world. - -```ts - const user = await this.userRepository.findOneBy({ - id: userId, -}); - -user?.runIt(function() { - this.emailService.send(this.email, `${this.name} welcome to the Katxupa library`); -}); -``` - -You can execute a block of code only if a value is neither null nor undefined: -```ts -const data: string | null = await getData(); - -data?.alsoIt(it => console.log(`Already initialized: ${it}`)) ?? console.log("Still not initialized"); -``` -The above code is equivalent to: -```ts -if (data != null && data != undefined) - console.log(`Already initialized: ${str!}`); -else - console.log("Still not initialized"); -``` - -The usage of **_takeIf_** & **_takeUnless_** is a bit different. You can call any value with **_takeIf_** and it will -return the caller instance if the predicate is true, or undefined if it's false (and vice versa when using **_takeUnless_**). -```ts -const account = await accountService.getAccount(id); - -account.takeIf(it => { - return addressBook.has(it.email); -})?.alsoIt(it => { - emailService.send(it.email, "You are entitled for crypto airdrop") -}) ?? console.log(`Account with ${id} not found in the system`); -``` - -### Null Safety -* Null-safety through [Optional Chaining Operator](https://github.com/tc39/proposal-optional-chaining) for scope functions: -```ts -// Only run the code block if "numberOrUndefined" is defined -const numberOrUndefinedOrNull = await bitcoinService.getPrice(); -numberOrUndefinedOrNull?.letIt((it) => { - it++; - it = it * 100; - return it; -}); - -// Actually, there is no need to declare a variable -(await bitcoinService.getPrice()) - ?.letIt((it) => { - it++; - it = it * 100; - return it; - }); -``` -* **_Optional_** wrapper for general purpose: -```ts -// Example 1 -// Get Usecase: -// 1- Validate if user exists -// 2- Through an HttpError if not -// 3- Return the user object -return optionalOf(user) - .orElseThrow(() => new NotFoundError("User doesn't exist")) - .get(); - -// Example 2 -// Delete Usecase: -// 1- Validate if user exists -// 2- Through an HttpError if not -// 3- Delete the user from the database asynchronously and await for the result -await Optional.of(user) - .orElseThrow(() => new HttpError(409, "User doesn't exist")) - .runAsync(() => this.userRepository.delete({id: userId})); - -// Example 3 -// Update usecase: -// 1- Validate if user exists -// 2- Through an HttpError if not -// 3- If exists, merge the existing one with additional userData -// 4- Call the user repository and save the updated user asyncronously, returning a promise -// -return optionalOf(user) - .orElseThrow(() => new HttpError(409, "User doesn't exist")) - .map(user => { - return { - ...user, - userData, - }; - }) - .runAsync(user => this.userRepository.save(user)); -``` - -### Duration -An easy, expressive and functional way of declaring a duration of time with support for various units (nanoseconds, -microseconds, milliseconds, seconds, minutes, hours, and days). - -```ts -// Example 1 -durationOf(1000) - .inWholeSeconds() - .letIt(it => { - console.log(`1000 milliseconds are the same as ${it} seconds`); - }); - -// Example 2 -const oneYearInMinutes = (1).years().inWholeMinutes(); -console.log(`1 year is ${oneYearInMinutes} minutes.`); - -// Example 3 -const duration = (1).years().add((6).months()).toString(); -console.log(duration); // Output: 548d 0h 0m 0s 0ns -``` - -### Range -The `Range` class provides utility methods for working with numeric ranges. - -```ts -// Example 1: Creating a Numeric Range -const numericRange = Range.rangeTo(1, 5, 2); -console.log(numericRange); // Output: [1, 3, 5] - -// Example 2: Creating a Numeric Range (Exclusive) -const numericRangeAlias = rangeUntil(1, 5, 2); -console.log(numericRangeAlias); // Output: [1, 3, 5] - -// Example 3: Checking if a Value is in Range -const isInRange = Range.inRange(3, 1, 5); -console.log(isInRange); // Output: true - -// Example 4: Range with chaining Operations -rangeTo(1, 5, 2) - .runIt(function () { - console.log(`multiplying the following range of numbers: ${this}`); - this.map(it => it * 2) - .forEach(it => console.log(it)); - }); -``` - -### Global Utility Functions -Global functions are the unsung heroes that transcend the boundaries of specific data types, providing a universal -toolkit for developers. These functions, residing in the global scope, are the go-to tools when you need versatile -and expressive solutions that operate seamlessly across various data structures. - -#### Meet some Ingredients -* **runIt()**: The maestro orchestrating the symphony of functions, _runIt_ calls a specified function block and presents its harmonious result. -* **withIt()**: The chameleon of functions, _withIt_ transforms any object into the star of the show, letting it shine in a function block tailored just for them. -* **listOf()**: Assemble an immutable list of elements effortlessly with _listOf_. It's your go-to for creating collections in a concise and readable manner. -* **mutableListOf()**: When you need a dynamic collection that can evolve with your needs, turn to _mutableListOf_ to create mutable lists with ease. -* **optionalOf()**: Embrace the power of optionals with _optionalOf_, a function that lets you gracefully handle scenarios with potentially absent values. -* **durationOf()**: Time is of the essence, and _durationOf_ allows you to craft time durations with precision, making time manipulation a breeze. -* **sequenceOf()**: Elevate your iteration game with _sequenceOf_, creating lazy sequences that conserve resources and provide on-the-fly transformation capabilities. -* **reducerOf()**: Transform your data with _reducerOf_, a function designed for building reducers that streamline complex state transformations in a functional paradigm. -* **rangeTo()**: Define ranges effortlessly with _rangeTo_, a function simplifying the creation of numeric ranges for iteration or data selection. -* **ok()**: Indicate success with confidence using _ok_. This function constructs an "ok" result, signaling that a task or operation was completed successfully. -* **error()**: Handle errors gracefully with _error_. This function constructs an error result, encapsulating details about the failure and allowing for structured error handling. - -These are just a smell of the utility this library brings to the table. Please, check the complete list in the [Global Functions]() section. - -### Type Extension Functions -In JavaScript, where each data type carries its own set of behaviors, type extension functions emerge as the virtuosos of customization. -These functions enrich your interactions with core data types, injecting them with new capabilities, being functional -or utilities, and streamlining common operations. - -| Type | Utilities | -|------------------------|---------------------------------------------------------------------------------------------------------------------------------------| -| [Object Extensions]() | Extensions redefine how you interact with objects, enabling fluid and expressive operations tailored to your needs. | -| [Number Extensions]() | Brings a consistent, functional and powerful approach to numeric operations | -| [String Extensions]() | Give your strings a makeover with extensions that redefine the way you manipulate text. | -| [Boolean Extensions]() | Functions like letIt, also, runIt, apply, takeIf, and takeUnless introduce a consistent and expressive way to handle boolean values. | +# Documentation diff --git a/docs/array.md b/docs/array.md deleted file mode 100644 index ff0a540..0000000 --- a/docs/array.md +++ /dev/null @@ -1,539 +0,0 @@ - -```markdown ---- -id: array -title: Array Component -sidebar_label: Array ---- - -## Introduction - -The Array component in the Katxupa library provides additional utility functions for working with arrays. - -### Installation - -To use the Array component, you can include it in your project: - -```bash -npm install katxupa -``` - -### Usage - -#### listOf - -Creates an immutable list from the provided elements. - -```javascript -const list = listOf(1, 2, 3); -// list is [1, 2, 3] -``` - -#### mutableListOf - -Creates a mutable list from the provided elements. - -```javascript -const mutableList = mutableListOf(1, 2, 3); -// mutableList is [1, 2, 3] -``` - -#### emptyList - -Creates an empty list. - -```javascript -const empty = emptyList(); -// empty is [] -``` - -#### associateWith - -Associates each element with a key-value pair based on the provided selectors. - -```javascript -const elements = [ - { id: 1, value: 'a' }, - { id: 2, value: 'b' }, -]; -const keyValuePairs = elements.associateWith( - (element) => element.id, - (element) => element.value -); -// keyValuePairs is { '1': 'a', '2': 'b' } -``` - -#### mapIndexed - -Maps each element to a new value using the provided transformation function. - -```javascript -const numbers = [1, 2, 3]; -const squaredNumbers = numbers.mapIndexed((num, index) => num * num + index); -// squaredNumbers is [1, 5, 11] -``` - -#### sortDescending - -Sorts the collection in descending order. - -```javascript -const numbers = [3, 1, 4, 1, 5, 9, 2]; -const sortedNumbers = numbers.sortDescending(); -// sortedNumbers is [9, 5, 4, 3, 2, 1, 1] -``` - -#### sortBy - -Sorts the collection using the provided comparator function. - -```javascript -const users = [ - { name: 'John', age: 30 }, - { name: 'Alice', age: 25 }, - { name: 'Bob', age: 35 }, -]; -const sortedUsers = users.sortBy((a, b) => a.age - b.age); -// sortedUsers is [{ name: 'Alice', age: 25 }, { name: 'John', age: 30 }, { name: 'Bob', age: 35 }] -``` - -#### plus - -Concatenates the collection with another array. - -```javascript -const collection = [1, 2, 3]; -const otherArray = [4, 5, 6]; -const result = collection.plus(otherArray); -// result is [1, 2, 3, 4, 5, 6] -``` - -#### minus - -Removes elements from the collection that are present in another array. - -```javascript -const collection = [1, 2, 3, 4, 5]; -const elementsToRemove = [3, 5]; -const result = collection.minus(elementsToRemove); -// result is [1, 2, 4] -``` - -#### minusAssign - -Removes elements from the collection that are present in another array (mutates the collection). - -```javascript -const collection = [1, 2, 3, 4, 5]; -const elementsToRemove = [3, 5]; -collection.minusAssign(elementsToRemove); -// collection is now [1, 2, 4] -``` - -#### plusAssign - -Appends elements from another array to the collection (mutates the collection). - -```javascript -const collection = [1, 2, 3]; -const additionalElements = [4, 5, 6]; -collection.plusAssign(additionalElements); -// collection is now [1, 2, 3, 4, 5, 6] -``` - -#### count - -Returns the number of elements in the collection. - -```javascript -const collection = [1, 2, 3, 4, 5]; -const count = collection.count(); -// count is 5 -``` - -#### removeAll - -Removes elements from the collection based on a predicate or a collection of elements. - -```javascript -const collection = [1, 2, 3, 4, 5]; -const elementsToRemove = [3, 5]; -const result = collection.removeAll(elementsToRemove); -// result is [1, 2, 4] -``` - -#### retainAll - -Retains only the elements in the collection that are present in another array. - -```javascript -const collection = [1, 2, 3, 4, 5]; -const elementsToRetain = [3, 5]; -const result = collection.retainAll(elementsToRetain); -// result is [3, 5] -``` - -#### last - -Returns the last element in the collection. - -```javascript -const collection = [1, 2, 3]; -const lastElement = collection.last(); -// lastElement is 3 -``` - -#### getOrElse - -Gets the element at the specified index or provides a default value if the index is out of bounds. - -```javascript -const collection = [1, 2, 3, 4, 5]; -const element = collection.getOrElse(2, () => 10); -// element is 3 -``` - -#### getOrEmpty - -Gets an optional containing the element at the specified index. - -```javascript -const collection = [1, 2, 3, 4, 5]; -const optionalElement = collection.getOrEmpty(2); -// optionalElement contains the value Optional.of(3) -``` - -#### shuffle - -Shuffles the elements in the collection randomly. - -```javascript -const collection = [1, 2, 3, 4, 5]; -collection.shuffle(); -// collection is now shuffled randomly, e.g., [3, 1, 5, 2, 4] -``` - -## API Reference - -### Methods - -- [associateWith](#associateWith) -- [mapIndexed](#mapIndexed) -- [sortDescending](#sortDescending) -- [sortBy](#sortBy) -- [plus](#plus) -- [minus](#minus) -- [minusAssign](#minusAssign) -- [plusAssign](#plusAssign) -- [count](#count) -- [removeAll](#removeAll) -- [retainAll](#retainAll) -- [last](#last) -- [getOrElse](#getOrElse) -- [getOrEmpty](#getOrEmpty) -- [shuffle](#shuffle) - -### associateWith - -Associates each element with a key-value pair based on the provided selectors. - -#### Parameters - -- `keySelector: (element: T) => K` - The function to extract keys from elements. -- `valueSelector: (element: T) => V` - The function to extract values from elements. - -#### Returns - -A record associating keys with their corresponding values. - -#### Example - -```javascript -const elements = [ - { id: 1, value: 'a' }, - { id: 2, value: 'b' }, -]; -const keyValuePairs = elements.associateWith( - (element) => element.id, - (element) => element.value -); -// keyValuePairs is { '1': 'a', '2': 'b' } -``` - -### mapIndexed - -Maps each element to a new value using the provided transformation function. - -#### Parameters - -- `transform: (element: T, index: number) => U` - The function to transform each element. - -#### Returns - -A readonly array containing the transformed elements. - -#### Example - -```javascript -const numbers = [1, 2, 3]; -const squaredNumbers = numbers.mapIndexed((num, index) => num * num + index); -// squaredNumbers is [1, 5, 11] -``` - -### sortDescending - -Sorts the collection in descending order. - -#### Returns - -A reference to the sorted array. - -#### Example - -```javascript -const numbers = [3, 1, 4, 1, 5, 9, 2]; -numbers.sortDescending(); -// numbers is now [9, 5, 4, 3, 2, 1, 1] -``` - -### sortBy - -Sorts the collection using the provided comparator function. - -#### Parameters - -- `comparator: (a: T, b: T) => number` - The function to compare elements. - -#### Returns - -A reference to the sorted array. - -#### Example - -```javascript -const users = [ - { name: 'John', age: 30 }, - { name: 'Alice', age: 25 }, - { name: 'Bob', age: 35 }, -]; -users.sortBy((a, b) => a.age - b.age); -// users is now sorted by age: [{ name: 'Alice', age: 25 }, { name: 'John', age: 30 }, { name: 'Bob', age: 35 }] -``` - -### plus - -Concatenates the collection with another array. - -#### Parameters - -- `other: T[]` - The array to concatenate with the current collection. - -#### Returns - -A new array containing elements from both the current collection and the provided array. - -#### Example - -```javascript -const collection = [1, 2, 3]; -const otherArray = [4, 5, 6]; -const result = collection.plus(otherArray); -// result is [1, 2, 3, 4, 5, 6] -``` - -### minus - -Removes elements from the collection that are present in another array. - -#### Parameters - -- `other: T[]` - The array containing elements to be removed from the current collection. - -#### Returns - -A new array with elements not present in the provided array. - -#### Example - -```javascript -const collection = [1, 2, 3, 4, 5]; -const elementsToRemove = [3, 5]; -const result = collection.minus(elementsToRemove); -// result is [1, 2, 4] -``` - -### minusAssign - -Removes elements from the collection that are present in another array (mutates the collection). - -#### Parameters - -- `collection: T[]` - The array containing elements to be removed from the current collection. - -#### Returns - -A reference to the affected array. - -#### Example - -```javascript -const collection = [1, 2, 3, 4, 5]; -const elementsToRemove = [3, 5]; -collection.minusAssign(elementsToRemove); -// collection is now [1, 2, 4] -``` - -### plusAssign - -Appends elements from another array to the collection (mutates the collection). - -#### Parameters - -- `other: T[]` - The array containing elements to be added to the current collection. - -#### Returns - -A reference to the affected array. - -#### Example - -```javascript -const collection = [1, 2, 3]; -const additionalElements = [4, 5, 6]; -collection.plusAssign(additionalElements); -// collection is now [1, 2, 3, 4, 5, 6] -``` - -### count - -Returns the number of elements in the collection. - -#### Returns - -The number of elements in the collection. - -#### Example - -```javascript -const collection = [1, 2, 3, 4, 5]; -const count = collection.count(); -// count is 5 -``` - -### removeAll - -Removes elements from the collection based on a predicate or a collection of elements. - -#### Parameters - -- `predicate: ((item: T) => boolean) | T[]` - The predicate function or collection of elements to remove. - -#### Returns - -A new array with elements removed based on the provided predicate or collection. - -#### Example - -```javascript -const collection = [1, 2, 3, 4, 5]; -const elementsToRemove = [3, 5]; -const result = collection.removeAll(elementsToRemove); -// result is [1, 2, 4] -``` - -### retainAll - -Retains only the elements in the collection that are present in another array. - -#### Parameters - -- `predicate: ((item: T) => boolean) | T[]` - The predicate function or collection of elements to retain. - -#### Returns - -A new array containing only the elements that satisfy the provided predicate or are present in the provided collection. - -#### Example - -```javascript -const collection = [1, 2, 3, 4, 5]; -const elementsToRetain = [3, 5]; -const result = collection.retainAll(elementsToRetain); -// result is [3, 5] -``` - -### last - -Returns the last element in the collection. - -#### Returns - -The last element in the collection. - -#### Throws - -- `NoSuchElementError` - If the collection is empty. - -#### Example - -```javascript -const collection = [1, 2, 3]; -const lastElement = collection.last(); -// lastElement is 3 -``` - -### getOrElse - -Gets the element at the specified index or provides a default value if the index is out of bounds. - -#### Parameters - -- `index: number` - The index of the element to retrieve. -- `defaultValueProvider: () => T` - A function providing the default value. - -#### Returns - -The element at the specified index or the default value if the index is out of bounds. - -#### Example - -```javascript -const collection = [1, 2, 3, 4, 5]; -const element = collection.getOrElse(2, () => 10); -// element is 3 -``` - -### getOrEmpty - -Gets an optional containing the element at the specified index. - -#### Parameters - -- `index: number` - The index of the element. - -#### Returns - -An optional containing the element if it exists, otherwise an empty optional. - -#### Example - -```javascript -const collection = [1, 2, 3, 4, 5]; -const optionalElement = collection.getOrEmpty(2); -// optionalElement contains the value Optional.of(3) -``` - -### shuffle - -Shuffles the elements in the collection randomly. - -#### Returns - -A reference to the affected array. - -#### Example - -```javascript -const collection = [1, 2, 3, 4, 5]; -collection.shuffle(); -// collection is now shuffled randomly, e.g., [3, 1, 5, 2, 4] diff --git a/docs/assets/docs-home.png b/docs/assets/docs-home.png new file mode 100644 index 0000000..1aa9175 Binary files /dev/null and b/docs/assets/docs-home.png differ diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 9343001..0000000 --- a/docs/index.md +++ /dev/null @@ -1,261 +0,0 @@ -# Katxupa -**Delicious Dish for Typescript and JavaScript projects.** - -In [Cape Verde](https://en.wikipedia.org/wiki/Cape_Verde) we have a saying: - -"_Put a person to work in the field and serve them anything other than [Katxupa](https://www.crumbsnatched.com/cachupa-traditional-dish-of-cape-verde/) -for breakfast, and you'll notice a decline in productivity and motivation. Therefore, give them Katxupa and spice it up on the side._" - -Just as "_Katxupa_" is an essential part of Cape Verdean culture, this library brings _functional_ elements to enhance your -productivity and developer happiness. So, consume (use) it! - -> **Katxupa**, Cape Verde’s national dish, is a flavorful stew consisting of hominy, beans, seasoned meats, and vegetables. -> Each family has its unique version, leading to delightful variations. -> One undeniable fact: there is no Cape Verdean who doesn't appreciate Katxupa ("Cachupa") — whether for breakfast, lunch, dinner, or any time, anywhere. - -## Why Katxupa -For starters, the "_K_" in **Katxupa** stands for [Kotlin](https://kotlinlang.org/), which was the primary inspiration for this library. Drawing from the -functional programming paradigm of Kotlin and its concise yet expressive syntax, Katxupa aims to bring similar benefits -to Typescript and JavaScript developers. - -### What Makes Katxupa Special? -* **Functional Delight**: _Katxupa_ introduces functional programming concepts to enhance your code's expressiveness and clarity. - -* **Kotlin-Inspired Goodness**: Leveraging lessons learned from Kotlin, _Katxupa_ provides utilities and extensions that streamline your workflow. - -* **Boosted Productivity**: Enjoy a more productive development experience with _Katxupa_'s utility classes, sequences, durations, and more. - -* **Developer Happiness**: Inspired by the joy of coding in Kotlin, Katxupa seeks to bring happiness to your TypeScript and JavaScript projects. - -### Key Features -* **Scope Functions**: _Kotlin-like_ scope functions, provides a set of functions to execute a block of code in the context of a given object: _letIt_, _runIt_, _withIt_, _apply_, and _also_. - -* **Collections Functions**: _Kotlin-like_ functions for Arrays, Maps, and Sets: Apply concise and expressive operations on collections. - -* **Sequences**: Lazy sequences with a _Kotlin-esque_ feel, providing a convenient way to work with iterable data. - -* **Duration**: A flexible and comprehensive time duration class with support for various units, offering better time handling. - -* **Optional**: A type that represents an optional value, helping to avoid null or undefined-related issues. - -* **Result and Either**: Functional constructs to handle success, errors, and alternate paths in a more expressive manner. - -* **Inspired by Cape Verde**: Infused with the spirit of [Cape Verde](https://en.wikipedia.org/wiki/Cape_Verde) and its cherished dish **Katxupa**, this library aims to add flavor to your coding experience. - -### Get a Taste of Katxupa -Explore the documentation and see how Katxupa can bring a delightful touch to your TypeScript and JavaScript projects. -From functional programming utilities to time handling and result handling, **Katxupa** is here to make your coding journey _more enjoyable_. - -## Installation -This package is build up with simplicity in mind, brings no additional dependencies, and it's published in NPM https://www.npmjs.com/package/katxupa. - -It can be installed using your preferred package manager. - -### NPM -```shell -npm install katxupa -``` - -### PNPM -```shell -pnpm install katxupa -``` - -### YARN -```shell -yarn add katxupa -``` - -## Usage -### Scope Functions -Simply call any value with **_letIt_**, **_runIt_**, **_also_** or **_apply_**, and it'll be passed as the argument or the context of a scope function. - -```ts linenums="1" -const person = {name: "Manuel", email: "ney.br.santos@gmail.com", age: 35}; - -person.letIt(it => { - console.log(`${it.name},`); - it.age < 30 ? console.log("A Young Man") : console.log("An Old Man"); - return it.age; -}).also(it => { - console.log(`Actual Age is ${it}`); -}); -// Output: -// Manuel, -// An Old Man -// Actual Age is 35 -``` - -It also supports the use of the new [Optional Chaining Operator](https://github.com/tc39/proposal-optional-chaining), -bringing the logic of [Kotlin's Null Safe Calls](https://kotlinlang.org/docs/reference/null-safety.html) to the JavaScript world. - -```ts linenums="1" - const user = await this.userRepository.findOneBy({ - id: userId, -}); - -user?.runIt(function() { - this.emailService.send(this.email, `${this.name} welcome to the Katxupa library`); -}); -``` - -You can execute a block of code only if a value is neither null nor undefined: -```ts linenums="1" -const data: string | null = await getData(); - -data?.also(it => console.log(`Already initialized: ${it}`)) ?? console.log("Still not initialized"); -``` -The above code is equivalent to: -```ts linenums="1" -if (data != null && data != undefined) - console.log(`Already initialized: ${str!}`); -else - console.log("Still not initialized"); -``` - -The usage of **_takeIf_** & **_takeUnless_** is a bit different. You can call any value with **_takeIf_** and it will -return the caller instance if the predicate is true, or undefined if it's false (and vice versa when using **_takeUnless_**). -```ts linenums="1" -const account = await accountService.getAccount(id); - -account.takeIf(it => { - return addressBook.has(it.email); -})?.also(it => { - emailService.send(it.email, "You are entitled for crypto airdrop") -}) ?? console.log(`Account with ${id} not found in the system`); -``` - -### Null Safety -* Null-safety through [Optional Chaining Operator](https://github.com/tc39/proposal-optional-chaining) for scope functions: -```ts linenums="1" -// Only run the code block if "numberOrUndefined" is defined -const numberOrUndefinedOrNull = await bitcoinService.getPrice(); -numberOrUndefinedOrNull?.letIt((it) => { - it++; - it = it * 100; - return it; -}); - -// Actually, there is no need to declare a variable -(await bitcoinService.getPrice()) - ?.letIt((it) => { - it++; - it = it * 100; - return it; - }); -``` -* **_Optional_** wrapper for general purpose: -```ts linenums="1" -// Example 1 -// Get Usecase: -// 1- Validate if user exists -// 2- Through an HttpError if not -// 3- Return the user object -return optionalOf(user) - .orElseThrow(() => new NotFoundError("User doesn't exist")) - .get(); - -// Example 2 -// Delete Usecase: -// 1- Validate if user exists -// 2- Through an HttpError if not -// 3- Delete the user from the database asynchronously and await for the result -await Optional.of(user) - .orElseThrow(() => new HttpError(409, "User doesn't exist")) - .runAsync(() => this.userRepository.delete({id: userId})); - -// Example 3 -// Update usecase: -// 1- Validate if user exists -// 2- Through an HttpError if not -// 3- If exists, merge the existing one with additional userData -// 4- Call the user repository and save the updated user asyncronously, returning a promise -// -return optionalOf(user) - .orElseThrow(() => new HttpError(409, "User doesn't exist")) - .map(user => { - return { - ...user, - userData, - }; - }) - .runAsync(user => this.userRepository.save(user)); -``` - -### Duration -An easy, expressive and functional way of declaring a duration of time with support for various units (nanoseconds, -microseconds, milliseconds, seconds, minutes, hours, and days). - -```ts linenums="1" -// Example 1 -durationOf(1000) - .toSeconds() - .letIt(it => { - console.log(`1000 milliseconds are the same as ${it} seconds`); - }); - -// Example 2 -const oneYearInMinutes = (1).years().toHours().toMinutes(); -console.log(`1 year is approximately ${oneYearInMinutes} minutes.`); - -// Example 3 -const duration = (1).years().add((6).months()).toString(); -console.log(duration); // Output: 548d 0h 0m 0s 0ns -``` - -### Range -The `Range` class provides utility methods for working with numeric ranges. - -```ts linenums="1" -// Example 1: Creating a Numeric Range -const numericRange = Range.rangeTo(1, 5, 2); -console.log(numericRange); // Output: [1, 3, 5] - -// Example 2: Creating a Numeric Range (Exclusive) -const numericRangeAlias = rangeUntil(1, 5, 2); -console.log(numericRangeAlias); // Output: [1, 3, 5] - -// Example 3: Checking if a Value is in Range -const isInRange = Range.inRange(3, 1, 5); -console.log(isInRange); // Output: true - -// Example 4: Range with chaining Operations -rangeTo(1, 5, 2) - .runIt(function () { - console.log(`multiplying the following range of numbers: ${this}`); - this.map(it => it * 2) - .forEach(it => console.log(it)); - }); -``` - -### Global Utility Functions -Global functions are the unsung heroes that transcend the boundaries of specific data types, providing a universal -toolkit for developers. These functions, residing in the global scope, are the go-to tools when you need versatile -and expressive solutions that operate seamlessly across various data structures. - -#### Meet some Ingredients -* **runIt()**: The maestro orchestrating the symphony of functions, _runIt_ calls a specified function block and presents its harmonious result. -* **withIt()**: The chameleon of functions, _withIt_ transforms any object into the star of the show, letting it shine in a function block tailored just for them. -* **listOf()**: Assemble an immutable list of elements effortlessly with _listOf_. It's your go-to for creating collections in a concise and readable manner. -* **mutableListOf()**: When you need a dynamic collection that can evolve with your needs, turn to _mutableListOf_ to create mutable lists with ease. -* **optionalOf()**: Embrace the power of optionals with _optionalOf_, a function that lets you gracefully handle scenarios with potentially absent values. -* **durationOf()**: Time is of the essence, and _durationOf_ allows you to craft time durations with precision, making time manipulation a breeze. -* **sequenceOf()**: Elevate your iteration game with _sequenceOf_, creating lazy sequences that conserve resources and provide on-the-fly transformation capabilities. -* **reducerOf()**: Transform your data with _reducerOf_, a function designed for building reducers that streamline complex state transformations in a functional paradigm. -* **rangeTo()**: Define ranges effortlessly with _rangeTo_, a function simplifying the creation of numeric ranges for iteration or data selection. -* **ok()**: Indicate success with confidence using _ok_. This function constructs an "ok" result, signaling that a task or operation was completed successfully. -* **error()**: Handle errors gracefully with _error_. This function constructs an error result, encapsulating details about the failure and allowing for structured error handling. - -These are just a smell of the utility this library brings to the table. Please, check the complete list in the [Global Functions]() section. - -### Type Extension Functions -In JavaScript, where each data type carries its own set of behaviors, type extension functions emerge as the virtuosos of customization. -These functions enrich your interactions with core data types, injecting them with new capabilities, being functional -or utilities, and streamlining common operations. - -| Type | Utilities | -|------------------------|---------------------------------------------------------------------------------------------------------------------------------------| -| [Object Extensions]() | Extensions redefine how you interact with objects, enabling fluid and expressive operations tailored to your needs. | -| [Number Extensions]() | Brings a consistent, functional and powerful approach to numeric operations | -| [String Extensions]() | Give your strings a makeover with extensions that redefine the way you manipulate text. | -| [Boolean Extensions]() | Functions like letIt, also, runIt, apply, takeIf, and takeUnless introduce a consistent and expressive way to handle boolean values. | diff --git a/docs/index2.md b/docs/index2.md deleted file mode 100644 index fb8a6f3..0000000 --- a/docs/index2.md +++ /dev/null @@ -1,47 +0,0 @@ -# Katxupa -**Delicious Dish for Typescript and JavaScript projects.** - -In [Cape Verde](https://en.wikipedia.org/wiki/Cape_Verde) we have a saying: - -"_Put a person to work in the field and serve them anything other than [Katxupa](https://www.crumbsnatched.com/cachupa-traditional-dish-of-cape-verde/) -for breakfast, and you'll notice a decline in productivity and motivation. Therefore, give them Katxupa and spice it up on the side._" - -Just as "_Katxupa_" is an essential part of Cape Verdean culture, this library brings _functional_ elements to enhance your -productivity and developer happiness. So, consume (use) it! - -> **Katxupa**, Cape Verde’s national dish, is a flavorful stew consisting of hominy, beans, seasoned meats, and vegetables. -> Each family has its unique version, leading to delightful variations. -> One undeniable fact: there is no Cape Verdean who doesn't appreciate Katxupa ("Cachupa") — whether for breakfast, lunch, dinner, or any time, anywhere. - -## Why Katxupa -For starters, the "_K_" in **Katxupa** stands for [Kotlin](https://kotlinlang.org/), which was the primary inspiration for this library. Drawing from the -functional programming paradigm of Kotlin and its concise yet expressive syntax, Katxupa aims to bring similar benefits -to Typescript and JavaScript developers. - -### What Makes Katxupa Special? -* **Functional Delight**: _Katxupa_ introduces functional programming concepts to enhance your code's expressiveness and clarity. - -* **Kotlin-Inspired Goodness**: Leveraging lessons learned from Kotlin, _Katxupa_ provides utilities and extensions that streamline your workflow. - -* **Boosted Productivity**: Enjoy a more productive development experience with _Katxupa_'s utility classes, sequences, durations, and more. - -* **Developer Happiness**: Inspired by the joy of coding in Kotlin, Katxupa seeks to bring happiness to your TypeScript and JavaScript projects. - -### Key Features -* **Scope Functions**: _Kotlin-like_ scope functions, provides a set of functions to execute a block of code in the context of a given object: _letIt_, _runIt_, _withIt_, _apply_, and _also_. - -* **Collections Functions**: _Kotlin-like_ functions for Arrays, Maps, and Sets: Apply concise and expressive operations on collections. - -* **Sequences**: Lazy sequences with a _Kotlin-esque_ feel, providing a convenient way to work with iterable data. - -* **Duration**: A flexible and comprehensive time duration class with support for various units, offering better time handling. - -* **Optional**: A type that represents an optional value, helping to avoid null or undefined-related issues. - -* **Result and Either**: Functional constructs to handle success, errors, and alternate paths in a more expressive manner. - -* **Inspired by Cape Verde**: Infused with the spirit of [Cape Verde](https://en.wikipedia.org/wiki/Cape_Verde) and its cherished dish **Katxupa**, this library aims to add flavor to your coding experience. - -### Get a Taste of Katxupa -Explore the documentation and see how Katxupa can bring a delightful touch to your TypeScript and JavaScript projects. -From functional programming utilities to time handling and result handling, **Katxupa** is here to make your coding journey _more enjoyable_. diff --git a/docs/scope.md b/docs/scope.md deleted file mode 100644 index cbd2afb..0000000 --- a/docs/scope.md +++ /dev/null @@ -1,270 +0,0 @@ -## Scope Functions -The Katxupa library contains several functions whose sole purpose is to execute a block of code within the context of an object. -When you call such a function on an object with a lambda expression provided, it forms a temporary scope. In this scope, -you can access the object through _**it**_ or in some cases _**this**_. Such functions are called scope functions. - -There are five of them: **_letIt_**, **_runIt_**, **_withIt_**, **_applyIt_**, and **_alsoIt_**. - -Basically, these functions all perform the same action: execute a block of code on an object. What's different is how this -object becomes available inside the block and what the result of the whole expression is. - -Here's a typical example of how to use a scope function: -```ts -({name: "Manuel", age: 36}) - .letIt(it => { - console.log(it); - it.age++; - console.log(it); - }); -``` -If you write the same without letIt, you'll have to introduce a new variable and repeat its name whenever you use it. -```ts -const user = {name: "Manuel", age: 36}; -console.log(user); -user.age++; -console.log(user); -``` - -Scope functions don't introduce any new technical capabilities, but they can make your code more concise and readable. - -Due to the many similarities between scope functions, choosing the right one for your use case can be tricky. -The choice mainly depends on your intent and the consistency of use in your project. Below, we provide detailed descriptions -of the differences between scope functions and their conventions. - -### Function selection -To help you choose the right scope function for your purpose, we provide this table that summarizes the key differences between them. - -| Function | Object Reference | Return Value | Is extension function | -|----------|------------------|----------------|----------------------------------------------| -| letIt | it | Lambda Result | Yes | -| runIt | this | Lambda Result | Yes | -| runIt | - | Lambda Result | No: called without the context object | -| withIt | this | Lambda Result | No: takes the context object as an argument. | -| applyIt | this | Context Object | Yes | -| alsoIt | it | Context Object | Yes | - -> Note that **letIt** & **alsoIt** can be called with standard lambda/arrow functions, but because JavaScript arrow functions don't -> have an own this context, **runIt** & **applyIt** have to be called with standard functions. - -Detailed information about these functions is provided in the dedicated sections below. - -Here is a short guide for choosing scope functions depending on the intended purpose: -* Executing a lambda on non-nullable objects: **letIt** -* Introducing an expression as a variable in local scope: **letIt** -* Object configuration: **applyIt** -* Object configuration and computing the result: **runIt** -* Running statements where an expression is required: non-extension **runIt** -* Additional effects: **alsoIt** -* Grouping function calls on an object: **withIt** - -The use cases of different scope functions overlap, so you can choose which functions to use based on the specific -conventions used in your project or team. - -Although scope functions can make your code more concise, avoid overusing them: it can make your code hard to read and -lead to errors. We also recommend that you avoid nesting scope functions and be careful when chaining them because it's -easy to get confused about the current context object and value of this or it. - -### Distinctions -Because scope functions are similar in nature, it's important to understand the differences between them. There are two -main differences between each scope function: - -* The way they refer to the context object. -* Their return value. - -#### Context object: this or it -Inside the lambda passed to a scope function, the context object is available by a short reference instead of its actual name. -Each scope function uses one of two ways to reference the context object: as a function receiver (_this_) or as a lambda argument (_it_). -Both provide the same capabilities, so we describe the pros and cons of each for different use cases and provide recommendations for their use. - -```ts -function main() { - const str = "Hello" - // this - str.runIt(function () { - console.log(`The string's length: ${this.length}`) - } ); - - // it - str.letIt(it => { - console.log(`The string's length: ${it.length}`) - }) -} -``` -### Functions -To help you choose the right scope function for your use case, we describe them in detail and provide recommendations for use. -Technically, scope functions are interchangeable in many cases, so the examples show conventions for using them. - -#### letIt -* **The context object** is available as an argument (_it_). -* **The return value** is the lambda result. - -_letIt_ can be used to invoke one or more functions on results of call chains. -```ts -const data: Array | null = await idsFromFile(); - -const str = data?.letIt(it => convertToString(it)) ?? "empty"; -``` - -#### withIt -* **The context object** is available as a receiver (_this_). -* **The return value** is the lambda result. - -As _withIt_ is not an extension function: the context object is passed as an argument, but inside the lambda, it's available as a receiver (_this_). - -We recommend using _withIt_ for calling functions on the context object when you don't need to use the returned result. -In code, with can be read as "**with this object, do the following**." - -```ts -const numbers = mutableListOf("one", "two", "three"); - -withIt(numbers, function () { - console.log(`'withIt' is called with argument ${this}`); - console.log(`It contains ${this.length} elements`); -}); -``` - -You can also use withIt to introduce a helper object whose properties or functions are used for calculating a value. -```ts -const numbers = mutableListOf("one", "two", "three"); - -const firstAndLast = withIt(numbers, function () { - return `The first element is ${this.first()}, the last element is ${this.last()}` -}); -console.debug(firstAndLast); -``` - -#### runIt -* **The context object** is available as a receiver (this). -* **The return value** is the lambda result. - -_runIt_ does the same as _withIt_ but it is implemented as an extension function. So like _letIt_, you can call it on the context object using dot notation. - -_runIt_ is useful when your lambda function both initializes objects and computes the return value. - -```ts -const service = new MultiportService("https://api.example.com/data", 80) - -const result = service.runIt(function () { - this.port = 8080; - const result = this.query(prepareRequest()); - console.debug(`Request sent to port ${this.port}"`); - return result; -}); - -// the same code written with letIt() function: -const letResult = service.letIt(it => { - it.port = 8080; - const result = it.query(prepareRequest()); - console.debug(`Request sent to port ${it.port}"`); - return result; -}); -``` - -You can also invoke _runIt_ as a non-extension function. The non-extension variant of _runIt_ has no context object, but it still returns the lambda result. -Non-extension run lets you execute a block of several statements where an expression is required. -In code, non-extension _runIt_ can be read as "**run the code block and compute the result.**" - -```ts -const hexNumberRegex = runIt(() => { - const digits = "0-9" - const hexDigits = "A-Fa-f" - const sign = "+-" - - return new RegExp(`[${sign}]?[${digits}${hexDigits}]+`, "g"); -}); - -let match; -while ((match = hexNumberRegex.exec("+123 -FFFF !%*& 88 XYZ")) !== null) { - console.log(match[0]); -} -``` - -#### applyIt -* **The context object** is available as a receiver (this). -* **The return value** is the object itself. - -As _applyIt_ returns the context object itself, we recommend that you use it for code blocks that don't return a value and -that mainly operate on the members of the receiver object. The most common use case for _applyIt_ is for object configuration. -Such calls can be read as "**apply the following assignments to the object.**" - -```ts -const manuel = {name: "Manuel", age: 36}; - -manuel.applyIt(function () { - this.name = "Manuel Santos"; - this.age++; - (this as any)["country"] = "Portugal"; -}); -console.log(manuel) -``` -Another use case for _applyIt_ is to include _applyIt_ in multiple call chains for more complex processing. - -#### alsoIt -* **The context object** is available as an argument (_it_). -* **The return value** is the object itself. - -_alsoIt_ is useful for performing some actions that take the context object as an argument. -Use _alsoIt_ for actions that need a reference to the object rather than its properties and functions, or when you -don't want to shadow the _this_ reference from an outer scope. - -When you see also in code, you can read it as "**and also do the following with the object**." - -```ts -const numbers = mutableListOf("one", "two", "three"); - -numbers - .alsoIt(it => console.log(`The list elements before adding new one: ${it}`)) - .push("four"); -``` - -#### takeIf and takeUnless -In addition to scope functions, the _Katxupa_ standard library contains the functions **takeIf** and **takeUnless**. -These functions let you embed checks of an object's state in call chains. - -When called on an object along with a predicate, **takeIf** returns this object if it satisfies the given predicate. -Otherwise, it returns _undefined_. So, _takeIf_ is a filtering function for a single object. - -**takeUnless** has the opposite logic of _takeIf_. When called on an object along with a predicate, _takeUnless_ returns -_undefined_ if it satisfies the given predicate. Otherwise, it returns the object. - -When using _takeIf_ or _takeUnless_, the object is available as a lambda argument (_it_). - -```ts -const number: number = Math.floor(Math.random() * 100); - -const evenOrNull = number.takeIf(it => it % 2 == 0); -const oddOrNull = number.takeUnless(it => it % 2 == 0); - -console.log(`even: ${evenOrNull}, odd: ${oddOrNull}`); -``` -> When chaining other functions after takeIf and takeUnless, don't forget to perform a null check or use a safe call (_?._) because their return value is nullable. - -```ts -const str = "Hello"; -const caps = str.takeIf(it => it.length > 0)?.toUpperCase(); -//const caps = str.takeIf(it => it.length > 0).toUpperCase() //compilation error -console.debug(caps); -``` - -**takeIf** and **takeUnless** are especially useful in combination with scope functions. For example, you can chain -_takeIf_ and _takeUnless_ with _letIt_ to _runIt_ a code block on objects that match the given predicate. To do this, -call _takeIf_ on the object and then call let with a safe call (_?_). For objects that don't match the predicate, _takeIf_ -returns undefined and _letIt_ isn't invoked. - -```ts -function displaySubstringPosition(input: string, sub: string) { - input.indexOf(sub) - .takeIf(it => it >= 0) - ?.letIt(it => { - console.log(`The substring ${sub} is found in ${input}.`) - console.log(`Its start position is ${it}.`) - }); -} - -displaySubstringPosition("010000011", "11"); -displaySubstringPosition("010000011", "12"); - -// Output: -// The substring 11 is found in 010000011. -// Its start position is 7. -``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index a47c84c..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,100 +0,0 @@ -site_name: "Katxupa" -site_description: "Delicious Dish for Typescript and JavaScript projects" -edit_uri: "edit/main/docs/" -repo_url: "https://github.com/manusant/Katxupa" -site_url: "https://manusant.github.io/Katxupa" -site_author: Manuel Santos - -nav: - - Home: - - Overview: index.md - - Contributors: index.md - - Scope: - - Scope Functions: scope.md - - Initializer Functions: index2.md - - Type Extensions: - - String: index.md - - Number: index.md - - Boolean: index.md - - Array: array.md - - Map: index.md - - Set: index.md - -# Extensions -markdown_extensions: - - admonition - - abbr - - attr_list - - def_list - - footnotes - - tables - - fenced_code - - meta - - wikilinks - - md_in_html - - sane_lists - - toc: - # permalink: true - permalink: '#' - baselevel: 1 - separator: '_' - - pymdownx.emoji: - emoji_index: !!python/name:materialx.emoji.twemoji - emoji_generator: !!python/name:materialx.emoji.to_svg - - pymdownx.details - - pymdownx.highlight: - linenums: true - anchor_linenums: true - auto_title: true - - pymdownx.inlinehilite - - pymdownx.mark - - pymdownx.keys - - pymdownx.magiclink: - repo_url_shorthand: true - user: squidfunk - repo: mkdocs-material - - pymdownx.snippets: - auto_append: - - docs/assets/abbreviations.md - - pymdownx.tabbed: - alternate_style: true - - pymdownx.tasklist: - custom_checkbox: true - - pymdownx.superfences: - custom_fences: - - name: mermaid - class: mermaid - format: !!python/name:pymdownx.superfences.fence_code_format - -theme: - name: material - language: en - features: - - content.code.copy - - content.code.select - - content.code.annotate - - content.code.annotate - - navigation.instant - - navigation.tabs.sticky - - navigation.tabs - - header.autohide - - announce.dismiss - - search.suggest - - search.share - - navigation.footer - palette: - - scheme: default - primary: black - accent: light blue - toggle: - icon: material/toggle-switch-off-outline - name: Switch to dark mode - - scheme: slate - primary: black - accent: light blue - toggle: - icon: material/toggle-switch - name: Switch to light mode - font: - text: Roboto - code: Roboto Mono \ No newline at end of file diff --git a/site/404.html b/site/404.html deleted file mode 100644 index 0a999e5..0000000 --- a/site/404.html +++ /dev/null @@ -1,612 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - Katxupa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- -

404 - Not found

- -
-
- - -
- -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/site/array/index.html b/site/array/index.html deleted file mode 100644 index 75365fa..0000000 --- a/site/array/index.html +++ /dev/null @@ -1,2476 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Array - Katxupa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Skip to content - - -
-
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Array

- -
Markdown
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
---
-id: array
-title: Array Component
-sidebar_label: Array
----
-
-## Introduction
-
-The Array component in the Katxupa library provides additional utility functions for working with arrays.
-
-### Installation
-
-To use the Array component, you can include it in your project:
-
-```bash
-npm install katxupa
-
-

Usage#

-

listOf#

-

Creates an immutable list from the provided elements.

-
JavaScript
1
-2
const list = listOf(1, 2, 3);
-// list is [1, 2, 3]
-
-

mutableListOf#

-

Creates a mutable list from the provided elements.

-
JavaScript
1
-2
const mutableList = mutableListOf(1, 2, 3);
-// mutableList is [1, 2, 3]
-
-

emptyList#

-

Creates an empty list.

-
JavaScript
1
-2
const empty = emptyList();
-// empty is []
-
-

associateWith#

-

Associates each element with a key-value pair based on the provided selectors.

-
JavaScript
1
-2
-3
-4
-5
-6
-7
-8
-9
const elements = [
-  { id: 1, value: 'a' },
-  { id: 2, value: 'b' },
-];
-const keyValuePairs = elements.associateWith(
-  (element) => element.id,
-  (element) => element.value
-);
-// keyValuePairs is { '1': 'a', '2': 'b' }
-
-

mapIndexed#

-

Maps each element to a new value using the provided transformation function.

-
JavaScript
1
-2
-3
const numbers = [1, 2, 3];
-const squaredNumbers = numbers.mapIndexed((num, index) => num * num + index);
-// squaredNumbers is [1, 5, 11]
-
-

sortDescending#

-

Sorts the collection in descending order.

-
JavaScript
1
-2
-3
const numbers = [3, 1, 4, 1, 5, 9, 2];
-const sortedNumbers = numbers.sortDescending();
-// sortedNumbers is [9, 5, 4, 3, 2, 1, 1]
-
-

sortBy#

-

Sorts the collection using the provided comparator function.

-
JavaScript
1
-2
-3
-4
-5
-6
-7
const users = [
-  { name: 'John', age: 30 },
-  { name: 'Alice', age: 25 },
-  { name: 'Bob', age: 35 },
-];
-const sortedUsers = users.sortBy((a, b) => a.age - b.age);
-// sortedUsers is [{ name: 'Alice', age: 25 }, { name: 'John', age: 30 }, { name: 'Bob', age: 35 }]
-
-

plus#

-

Concatenates the collection with another array.

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3];
-const otherArray = [4, 5, 6];
-const result = collection.plus(otherArray);
-// result is [1, 2, 3, 4, 5, 6]
-
-

minus#

-

Removes elements from the collection that are present in another array.

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3, 4, 5];
-const elementsToRemove = [3, 5];
-const result = collection.minus(elementsToRemove);
-// result is [1, 2, 4]
-
-

minusAssign#

-

Removes elements from the collection that are present in another array (mutates the collection).

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3, 4, 5];
-const elementsToRemove = [3, 5];
-collection.minusAssign(elementsToRemove);
-// collection is now [1, 2, 4]
-
-

plusAssign#

-

Appends elements from another array to the collection (mutates the collection).

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3];
-const additionalElements = [4, 5, 6];
-collection.plusAssign(additionalElements);
-// collection is now [1, 2, 3, 4, 5, 6]
-
-

count#

-

Returns the number of elements in the collection.

-
JavaScript
1
-2
-3
const collection = [1, 2, 3, 4, 5];
-const count = collection.count();
-// count is 5
-
-

removeAll#

-

Removes elements from the collection based on a predicate or a collection of elements.

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3, 4, 5];
-const elementsToRemove = [3, 5];
-const result = collection.removeAll(elementsToRemove);
-// result is [1, 2, 4]
-
-

retainAll#

-

Retains only the elements in the collection that are present in another array.

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3, 4, 5];
-const elementsToRetain = [3, 5];
-const result = collection.retainAll(elementsToRetain);
-// result is [3, 5]
-
-

last#

-

Returns the last element in the collection.

-
JavaScript
1
-2
-3
const collection = [1, 2, 3];
-const lastElement = collection.last();
-// lastElement is 3
-
-

getOrElse#

-

Gets the element at the specified index or provides a default value if the index is out of bounds.

-
JavaScript
1
-2
-3
const collection = [1, 2, 3, 4, 5];
-const element = collection.getOrElse(2, () => 10);
-// element is 3
-
-

getOrEmpty#

-

Gets an optional containing the element at the specified index.

-
JavaScript
1
-2
-3
const collection = [1, 2, 3, 4, 5];
-const optionalElement = collection.getOrEmpty(2);
-// optionalElement contains the value Optional.of(3)
-
-

shuffle#

-

Shuffles the elements in the collection randomly.

-
JavaScript
1
-2
-3
const collection = [1, 2, 3, 4, 5];
-collection.shuffle();
-// collection is now shuffled randomly, e.g., [3, 1, 5, 2, 4]
-
-

API Reference#

-

Methods#

- -

associateWith#

-

Associates each element with a key-value pair based on the provided selectors.

-

Parameters#

-
    -
  • keySelector: (element: T) => K - The function to extract keys from elements.
  • -
  • valueSelector: (element: T) => V - The function to extract values from elements.
  • -
-

Returns#

-

A record associating keys with their corresponding values.

-

Example#

-
JavaScript
1
-2
-3
-4
-5
-6
-7
-8
-9
const elements = [
-  { id: 1, value: 'a' },
-  { id: 2, value: 'b' },
-];
-const keyValuePairs = elements.associateWith(
-  (element) => element.id,
-  (element) => element.value
-);
-// keyValuePairs is { '1': 'a', '2': 'b' }
-
-

mapIndexed#

-

Maps each element to a new value using the provided transformation function.

-

Parameters#

-
    -
  • transform: (element: T, index: number) => U - The function to transform each element.
  • -
-

Returns#

-

A readonly array containing the transformed elements.

-

Example#

-
JavaScript
1
-2
-3
const numbers = [1, 2, 3];
-const squaredNumbers = numbers.mapIndexed((num, index) => num * num + index);
-// squaredNumbers is [1, 5, 11]
-
-

sortDescending#

-

Sorts the collection in descending order.

-

Returns#

-

A reference to the sorted array.

-

Example#

-
JavaScript
1
-2
-3
const numbers = [3, 1, 4, 1, 5, 9, 2];
-numbers.sortDescending();
-// numbers is now [9, 5, 4, 3, 2, 1, 1]
-
-

sortBy#

-

Sorts the collection using the provided comparator function.

-

Parameters#

-
    -
  • comparator: (a: T, b: T) => number - The function to compare elements.
  • -
-

Returns#

-

A reference to the sorted array.

-

Example#

-
JavaScript
1
-2
-3
-4
-5
-6
-7
const users = [
-  { name: 'John', age: 30 },
-  { name: 'Alice', age: 25 },
-  { name: 'Bob', age: 35 },
-];
-users.sortBy((a, b) => a.age - b.age);
-// users is now sorted by age: [{ name: 'Alice', age: 25 }, { name: 'John', age: 30 }, { name: 'Bob', age: 35 }]
-
-

plus#

-

Concatenates the collection with another array.

-

Parameters#

-
    -
  • other: T[] - The array to concatenate with the current collection.
  • -
-

Returns#

-

A new array containing elements from both the current collection and the provided array.

-

Example#

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3];
-const otherArray = [4, 5, 6];
-const result = collection.plus(otherArray);
-// result is [1, 2, 3, 4, 5, 6]
-
-

minus#

-

Removes elements from the collection that are present in another array.

-

Parameters#

-
    -
  • other: T[] - The array containing elements to be removed from the current collection.
  • -
-

Returns#

-

A new array with elements not present in the provided array.

-

Example#

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3, 4, 5];
-const elementsToRemove = [3, 5];
-const result = collection.minus(elementsToRemove);
-// result is [1, 2, 4]
-
-

minusAssign#

-

Removes elements from the collection that are present in another array (mutates the collection).

-

Parameters#

-
    -
  • collection: T[] - The array containing elements to be removed from the current collection.
  • -
-

Returns#

-

A reference to the affected array.

-

Example#

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3, 4, 5];
-const elementsToRemove = [3, 5];
-collection.minusAssign(elementsToRemove);
-// collection is now [1, 2, 4]
-
-

plusAssign#

-

Appends elements from another array to the collection (mutates the collection).

-

Parameters#

-
    -
  • other: T[] - The array containing elements to be added to the current collection.
  • -
-

Returns#

-

A reference to the affected array.

-

Example#

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3];
-const additionalElements = [4, 5, 6];
-collection.plusAssign(additionalElements);
-// collection is now [1, 2, 3, 4, 5, 6]
-
-

count#

-

Returns the number of elements in the collection.

-

Returns#

-

The number of elements in the collection.

-

Example#

-
JavaScript
1
-2
-3
const collection = [1, 2, 3, 4, 5];
-const count = collection.count();
-// count is 5
-
-

removeAll#

-

Removes elements from the collection based on a predicate or a collection of elements.

-

Parameters#

-
    -
  • predicate: ((item: T) => boolean) | T[] - The predicate function or collection of elements to remove.
  • -
-

Returns#

-

A new array with elements removed based on the provided predicate or collection.

-

Example#

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3, 4, 5];
-const elementsToRemove = [3, 5];
-const result = collection.removeAll(elementsToRemove);
-// result is [1, 2, 4]
-
-

retainAll#

-

Retains only the elements in the collection that are present in another array.

-

Parameters#

-
    -
  • predicate: ((item: T) => boolean) | T[] - The predicate function or collection of elements to retain.
  • -
-

Returns#

-

A new array containing only the elements that satisfy the provided predicate or are present in the provided collection.

-

Example#

-
JavaScript
1
-2
-3
-4
const collection = [1, 2, 3, 4, 5];
-const elementsToRetain = [3, 5];
-const result = collection.retainAll(elementsToRetain);
-// result is [3, 5]
-
-

last#

-

Returns the last element in the collection.

-

Returns#

-

The last element in the collection.

-

Throws#

-
    -
  • NoSuchElementError - If the collection is empty.
  • -
-

Example#

-
JavaScript
1
-2
-3
const collection = [1, 2, 3];
-const lastElement = collection.last();
-// lastElement is 3
-
-

getOrElse#

-

Gets the element at the specified index or provides a default value if the index is out of bounds.

-

Parameters#

-
    -
  • index: number - The index of the element to retrieve.
  • -
  • defaultValueProvider: () => T - A function providing the default value.
  • -
-

Returns#

-

The element at the specified index or the default value if the index is out of bounds.

-

Example#

-
JavaScript
1
-2
-3
const collection = [1, 2, 3, 4, 5];
-const element = collection.getOrElse(2, () => 10);
-// element is 3
-
-

getOrEmpty#

-

Gets an optional containing the element at the specified index.

-

Parameters#

-
    -
  • index: number - The index of the element.
  • -
-

Returns#

-

An optional containing the element if it exists, otherwise an empty optional.

-

Example#

-
JavaScript
1
-2
-3
const collection = [1, 2, 3, 4, 5];
-const optionalElement = collection.getOrEmpty(2);
-// optionalElement contains the value Optional.of(3)
-
-

shuffle#

-

Shuffles the elements in the collection randomly.

-

Returns#

-

A reference to the affected array.

-

Example#

-

```javascript -const collection = [1, 2, 3, 4, 5]; -collection.shuffle(); -// collection is now shuffled randomly, e.g., [3, 1, 5, 2, 4]

- - - - - - -
-
- - -
- -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/site/assets/images/favicon.png b/site/assets/images/favicon.png deleted file mode 100644 index 1cf13b9..0000000 Binary files a/site/assets/images/favicon.png and /dev/null differ diff --git a/site/assets/javascripts/bundle.220ee61c.min.js b/site/assets/javascripts/bundle.220ee61c.min.js deleted file mode 100644 index 116072a..0000000 --- a/site/assets/javascripts/bundle.220ee61c.min.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict";(()=>{var Ci=Object.create;var gr=Object.defineProperty;var Ri=Object.getOwnPropertyDescriptor;var ki=Object.getOwnPropertyNames,Ht=Object.getOwnPropertySymbols,Hi=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,nn=Object.prototype.propertyIsEnumerable;var rn=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&rn(e,r,t[r]);if(Ht)for(var r of Ht(t))nn.call(t,r)&&rn(e,r,t[r]);return e};var on=(e,t)=>{var r={};for(var n in e)yr.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&Ht)for(var n of Ht(e))t.indexOf(n)<0&&nn.call(e,n)&&(r[n]=e[n]);return r};var Pt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Pi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ki(t))!yr.call(e,o)&&o!==r&&gr(e,o,{get:()=>t[o],enumerable:!(n=Ri(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Ci(Hi(e)):{},Pi(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var sn=Pt((xr,an)=>{(function(e,t){typeof xr=="object"&&typeof an!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(xr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(O){return!!(O&&O!==document&&O.nodeName!=="HTML"&&O.nodeName!=="BODY"&&"classList"in O&&"contains"in O.classList)}function f(O){var Qe=O.type,De=O.tagName;return!!(De==="INPUT"&&s[Qe]&&!O.readOnly||De==="TEXTAREA"&&!O.readOnly||O.isContentEditable)}function c(O){O.classList.contains("focus-visible")||(O.classList.add("focus-visible"),O.setAttribute("data-focus-visible-added",""))}function u(O){O.hasAttribute("data-focus-visible-added")&&(O.classList.remove("focus-visible"),O.removeAttribute("data-focus-visible-added"))}function p(O){O.metaKey||O.altKey||O.ctrlKey||(a(r.activeElement)&&c(r.activeElement),n=!0)}function m(O){n=!1}function d(O){a(O.target)&&(n||f(O.target))&&c(O.target)}function h(O){a(O.target)&&(O.target.classList.contains("focus-visible")||O.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(O.target))}function v(O){document.visibilityState==="hidden"&&(o&&(n=!0),Y())}function Y(){document.addEventListener("mousemove",N),document.addEventListener("mousedown",N),document.addEventListener("mouseup",N),document.addEventListener("pointermove",N),document.addEventListener("pointerdown",N),document.addEventListener("pointerup",N),document.addEventListener("touchmove",N),document.addEventListener("touchstart",N),document.addEventListener("touchend",N)}function B(){document.removeEventListener("mousemove",N),document.removeEventListener("mousedown",N),document.removeEventListener("mouseup",N),document.removeEventListener("pointermove",N),document.removeEventListener("pointerdown",N),document.removeEventListener("pointerup",N),document.removeEventListener("touchmove",N),document.removeEventListener("touchstart",N),document.removeEventListener("touchend",N)}function N(O){O.target.nodeName&&O.target.nodeName.toLowerCase()==="html"||(n=!1,B())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),Y(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var cn=Pt(Er=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},s=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(B,N){d.append(N,B)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(O){throw new Error("URL unable to set base "+c+" due to "+O)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,Y=!0,B=this;["append","delete","set"].forEach(function(O){var Qe=h[O];h[O]=function(){Qe.apply(h,arguments),v&&(Y=!1,B.search=h.toString(),Y=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var N=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==N&&(N=this.search,Y&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},s=i.prototype,a=function(f){Object.defineProperty(s,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){a(f)}),Object.defineProperty(s,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(s,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er)});var qr=Pt((Mt,Nr)=>{/*! - * clipboard.js v2.0.11 - * https://clipboardjs.com/ - * - * Licensed MIT © Zeno Rocha - */(function(t,r){typeof Mt=="object"&&typeof Nr=="object"?Nr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Mt=="object"?Mt.ClipboardJS=r():t.ClipboardJS=r()})(Mt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return Ai}});var s=i(279),a=i.n(s),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(T){return!1}}var d=function(T){var E=p()(T);return m("cut"),E},h=d;function v(j){var T=document.documentElement.getAttribute("dir")==="rtl",E=document.createElement("textarea");E.style.fontSize="12pt",E.style.border="0",E.style.padding="0",E.style.margin="0",E.style.position="absolute",E.style[T?"right":"left"]="-9999px";var H=window.pageYOffset||document.documentElement.scrollTop;return E.style.top="".concat(H,"px"),E.setAttribute("readonly",""),E.value=j,E}var Y=function(T,E){var H=v(T);E.container.appendChild(H);var I=p()(H);return m("copy"),H.remove(),I},B=function(T){var E=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},H="";return typeof T=="string"?H=Y(T,E):T instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(T==null?void 0:T.type)?H=Y(T.value,E):(H=p()(T),m("copy")),H},N=B;function O(j){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?O=function(E){return typeof E}:O=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},O(j)}var Qe=function(){var T=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},E=T.action,H=E===void 0?"copy":E,I=T.container,q=T.target,Me=T.text;if(H!=="copy"&&H!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&O(q)==="object"&&q.nodeType===1){if(H==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(H==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Me)return N(Me,{container:I});if(q)return H==="cut"?h(q):N(q,{container:I})},De=Qe;function $e(j){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?$e=function(E){return typeof E}:$e=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},$e(j)}function Ei(j,T){if(!(j instanceof T))throw new TypeError("Cannot call a class as a function")}function tn(j,T){for(var E=0;E0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof I.action=="function"?I.action:this.defaultAction,this.target=typeof I.target=="function"?I.target:this.defaultTarget,this.text=typeof I.text=="function"?I.text:this.defaultText,this.container=$e(I.container)==="object"?I.container:document.body}},{key:"listenClick",value:function(I){var q=this;this.listener=c()(I,"click",function(Me){return q.onClick(Me)})}},{key:"onClick",value:function(I){var q=I.delegateTarget||I.currentTarget,Me=this.action(q)||"copy",kt=De({action:Me,container:this.container,target:this.target(q),text:this.text(q)});this.emit(kt?"success":"error",{action:Me,text:kt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(I){return vr("action",I)}},{key:"defaultTarget",value:function(I){var q=vr("target",I);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(I){return vr("text",I)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(I){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return N(I,q)}},{key:"cut",value:function(I){return h(I)}},{key:"isSupported",value:function(){var I=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof I=="string"?[I]:I,Me=!!document.queryCommandSupported;return q.forEach(function(kt){Me=Me&&!!document.queryCommandSupported(kt)}),Me}}]),E}(a()),Ai=Li},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,f){for(;a&&a.nodeType!==o;){if(typeof a.matches=="function"&&a.matches(f))return a;a=a.parentNode}}n.exports=s},438:function(n,o,i){var s=i(828);function a(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof m=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return a(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=s(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(n,o,i){var s=i(879),a=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(h))throw new TypeError("Third argument must be a Function");if(s.node(m))return c(m,d,h);if(s.nodeList(m))return u(m,d,h);if(s.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return a(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),s=f.toString()}return s}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,s,a){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var f=this;function c(){f.off(i,c),s.apply(a,arguments)}return c._=s,this.on(i,c,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=a.length;for(f;f{"use strict";/*! - * escape-html - * Copyright(c) 2012-2013 TJ Holowaychuk - * Copyright(c) 2015 Andreas Lubbe - * Copyright(c) 2015 Tiancheng "Timothy" Gu - * MIT Licensed - */var rs=/["'&<>]/;Yo.exports=ns;function ns(e){var t=""+e,r=rs.exec(t);if(!r)return t;var n,o="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],s;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(s)throw s.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||a(m,d)})})}function a(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof et?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){a("next",m)}function u(m){a("throw",m)}function p(m,d){m(d),i.shift(),i.length&&a(i[0][0],i[0][1])}}function pn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Ee=="function"?Ee(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(s){return new Promise(function(a,f){s=e[i](s),o(a,f,s.done,s.value)})}}function o(i,s,a,f){Promise.resolve(f).then(function(c){i({value:c,done:a})},s)}}function C(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var It=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: -`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` - `):"",this.name="UnsubscriptionError",this.errors=r}});function Ve(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ie=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Ee(s),f=a.next();!f.done;f=a.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var u=this.initialTeardown;if(C(u))try{u()}catch(v){i=v instanceof It?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=Ee(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{ln(h)}catch(v){i=i!=null?i:[],v instanceof It?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new It(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)ln(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ve(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ve(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Sr=Ie.EMPTY;function jt(e){return e instanceof Ie||e&&"closed"in e&&C(e.remove)&&C(e.add)&&C(e.unsubscribe)}function ln(e){C(e)?e():e.unsubscribe()}var Le={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,s=o.isStopped,a=o.observers;return i||s?Sr:(this.currentObservers=null,a.push(r),new Ie(function(){n.currentObservers=null,Ve(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,s=n.isStopped;o?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,n){return new xn(r,n)},t}(F);var xn=function(e){ie(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Sr},t}(x);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ie(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,s=n._infiniteTimeWindow,a=n._timestampProvider,f=n._windowTime;o||(i.push(r),!s&&i.push(a.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,s=o._buffer,a=s.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var s=r.actions;n!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Wt);var Sn=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Dt);var Oe=new Sn(wn);var M=new F(function(e){return e.complete()});function Vt(e){return e&&C(e.schedule)}function Cr(e){return e[e.length-1]}function Ye(e){return C(Cr(e))?e.pop():void 0}function Te(e){return Vt(Cr(e))?e.pop():void 0}function zt(e,t){return typeof Cr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Nt(e){return C(e==null?void 0:e.then)}function qt(e){return C(e[ft])}function Kt(e){return Symbol.asyncIterator&&C(e==null?void 0:e[Symbol.asyncIterator])}function Qt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function zi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Yt=zi();function Gt(e){return C(e==null?void 0:e[Yt])}function Bt(e){return un(this,arguments,function(){var r,n,o,i;return $t(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,et(r.read())];case 3:return n=s.sent(),o=n.value,i=n.done,i?[4,et(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,et(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Jt(e){return C(e==null?void 0:e.getReader)}function U(e){if(e instanceof F)return e;if(e!=null){if(qt(e))return Ni(e);if(pt(e))return qi(e);if(Nt(e))return Ki(e);if(Kt(e))return On(e);if(Gt(e))return Qi(e);if(Jt(e))return Yi(e)}throw Qt(e)}function Ni(e){return new F(function(t){var r=e[ft]();if(C(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function qi(e){return new F(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?A(function(o,i){return e(o,i,n)}):de,ge(1),r?He(t):Dn(function(){return new Zt}))}}function Vn(){for(var e=[],t=0;t=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new x}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,f=a===void 0?!0:a;return function(c){var u,p,m,d=0,h=!1,v=!1,Y=function(){p==null||p.unsubscribe(),p=void 0},B=function(){Y(),u=m=void 0,h=v=!1},N=function(){var O=u;B(),O==null||O.unsubscribe()};return y(function(O,Qe){d++,!v&&!h&&Y();var De=m=m!=null?m:r();Qe.add(function(){d--,d===0&&!v&&!h&&(p=$r(N,f))}),De.subscribe(Qe),!u&&d>0&&(u=new rt({next:function($e){return De.next($e)},error:function($e){v=!0,Y(),p=$r(B,o,$e),De.error($e)},complete:function(){h=!0,Y(),p=$r(B,s),De.complete()}}),U(O).subscribe(u))})(c)}}function $r(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function z(e,t=document){let r=ce(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ce(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),V(e===_e()),J())}function Xe(e){return{x:e.offsetLeft,y:e.offsetTop}}function Kn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>Xe(e)),V(Xe(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>rr(e)),V(rr(e)))}var Yn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!Wr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),va?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!Wr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ba.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Gn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Jn=typeof WeakMap!="undefined"?new WeakMap:new Yn,Xn=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=ga.getInstance(),n=new La(t,r,this);Jn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){Xn.prototype[e]=function(){var t;return(t=Jn.get(this))[e].apply(t,arguments)}});var Aa=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:Xn}(),Zn=Aa;var eo=new x,Ca=$(()=>k(new Zn(e=>{for(let t of e)eo.next(t)}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ye(e){return Ca.pipe(S(t=>t.observe(e)),g(t=>eo.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(()=>he(e)))),V(he(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var to=new x,Ra=$(()=>k(new IntersectionObserver(e=>{for(let t of e)to.next(t)},{threshold:0}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function sr(e){return Ra.pipe(S(t=>t.observe(e)),g(t=>to.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function ro(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=he(e),o=bt(e);return r>=o.height-n.height-t}),J())}var cr={drawer:z("[data-md-toggle=drawer]"),search:z("[data-md-toggle=search]")};function no(e){return cr[e].checked}function Ke(e,t){cr[e].checked!==t&&cr[e].click()}function Ue(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),V(t.checked))}function ka(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ha(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(V(!1))}function oo(){let e=b(window,"keydown").pipe(A(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:no("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),A(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!ka(n,r)}return!0}),pe());return Ha().pipe(g(t=>t?M:e))}function le(){return new URL(location.href)}function ot(e){location.href=e.href}function io(){return new x}function ao(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)ao(e,r)}function _(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)ao(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function so(){return location.hash.substring(1)}function Dr(e){let t=_("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Pa(e){return L(b(window,"hashchange"),e).pipe(l(so),V(so()),A(t=>t.length>0),X(1))}function co(e){return Pa(e).pipe(l(t=>ce(`[id="${t}"]`)),A(t=>typeof t!="undefined"))}function Vr(e){let t=matchMedia(e);return er(r=>t.addListener(()=>r(t.matches))).pipe(V(t.matches))}function fo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(V(e.matches))}function zr(e,t){return e.pipe(g(r=>r?t():M))}function ur(e,t={credentials:"same-origin"}){return ue(fetch(`${e}`,t)).pipe(fe(()=>M),g(r=>r.status!==200?Ot(()=>new Error(r.statusText)):k(r)))}function We(e,t){return ur(e,t).pipe(g(r=>r.json()),X(1))}function uo(e,t){let r=new DOMParser;return ur(e,t).pipe(g(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),X(1))}function pr(e){let t=_("script",{src:e});return $(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(g(()=>Ot(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),R(()=>document.head.removeChild(t)),ge(1))))}function po(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function lo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(po),V(po()))}function mo(){return{width:innerWidth,height:innerHeight}}function ho(){return b(window,"resize",{passive:!0}).pipe(l(mo),V(mo()))}function bo(){return G([lo(),ho()]).pipe(l(([e,t])=>({offset:e,size:t})),X(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(ee("size")),o=G([n,r]).pipe(l(()=>Xe(e)));return G([r,t,o]).pipe(l(([{height:i},{offset:s,size:a},{x:f,y:c}])=>({offset:{x:s.x-f,y:s.y-c+i},size:a})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(s=>{let a=document.createElement("script");a.src=i,a.onload=s,document.body.appendChild(a)})),Promise.resolve())}var r=class extends EventTarget{constructor(n){super(),this.url=n,this.m=i=>{i.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:i.data})),this.onmessage&&this.onmessage(i))},this.e=(i,s,a,f,c)=>{if(s===`${this.url}`){let u=new ErrorEvent("error",{message:i,filename:s,lineno:a,colno:f,error:c});this.dispatchEvent(u),this.onerror&&this.onerror(u)}};let o=document.createElement("iframe");o.hidden=!0,document.body.appendChild(this.iframe=o),this.w.document.open(),this.w.document.write(` - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Katxupa#

-

Delicious Dish for Typescript and JavaScript projects.

-

In Cape Verde we have a saying:

-

"Put a person to work in the field and serve them anything other than Katxupa -for breakfast, and you'll notice a decline in productivity and motivation. Therefore, give them Katxupa and spice it up on the side."

-

Just as "Katxupa" is an essential part of Cape Verdean culture, this library brings functional elements to enhance your -productivity and developer happiness. So, consume (use) it!

-
-

Katxupa, Cape Verde’s national dish, is a flavorful stew consisting of hominy, beans, seasoned meats, and vegetables. -Each family has its unique version, leading to delightful variations. -One undeniable fact: there is no Cape Verdean who doesn't appreciate Katxupa ("Cachupa") — whether for breakfast, lunch, dinner, or any time, anywhere.

-
-

Why Katxupa#

-

For starters, the "K" in Katxupa stands for Kotlin, which was the primary inspiration for this library. Drawing from the -functional programming paradigm of Kotlin and its concise yet expressive syntax, Katxupa aims to bring similar benefits -to Typescript and JavaScript developers.

-

What Makes Katxupa Special?#

-
    -
  • -

    Functional Delight: Katxupa introduces functional programming concepts to enhance your code's expressiveness and clarity.

    -
  • -
  • -

    Kotlin-Inspired Goodness: Leveraging lessons learned from Kotlin, Katxupa provides utilities and extensions that streamline your workflow.

    -
  • -
  • -

    Boosted Productivity: Enjoy a more productive development experience with Katxupa's utility classes, sequences, durations, and more.

    -
  • -
  • -

    Developer Happiness: Inspired by the joy of coding in Kotlin, Katxupa seeks to bring happiness to your TypeScript and JavaScript projects.

    -
  • -
-

Key Features#

-
    -
  • -

    Scope Functions: Kotlin-like scope functions, provides a set of functions to execute a block of code in the context of a given object: letIt, runIt, withIt, apply, and also.

    -
  • -
  • -

    Collections Functions: Kotlin-like functions for Arrays, Maps, and Sets: Apply concise and expressive operations on collections.

    -
  • -
  • -

    Sequences: Lazy sequences with a Kotlin-esque feel, providing a convenient way to work with iterable data.

    -
  • -
  • -

    Duration: A flexible and comprehensive time duration class with support for various units, offering better time handling.

    -
  • -
  • -

    Optional: A type that represents an optional value, helping to avoid null or undefined-related issues.

    -
  • -
  • -

    Result and Either: Functional constructs to handle success, errors, and alternate paths in a more expressive manner.

    -
  • -
  • -

    Inspired by Cape Verde: Infused with the spirit of Cape Verde and its cherished dish Katxupa, this library aims to add flavor to your coding experience.

    -
  • -
-

Get a Taste of Katxupa#

-

Explore the documentation and see how Katxupa can bring a delightful touch to your TypeScript and JavaScript projects. -From functional programming utilities to time handling and result handling, Katxupa is here to make your coding journey more enjoyable.

-

Installation#

-

This package is build up with simplicity in mind, brings no additional dependencies, and it's published in NPM https://www.npmjs.com/package/katxupa.

-

It can be installed using your preferred package manager.

-

NPM#

-
Bash
npm install katxupa
-
-

PNPM#

-
Bash
pnpm install katxupa
-
-

YARN#

-
Bash
yarn add katxupa
-
-

Usage#

-

Scope Functions#

-

Simply call any value with letIt, runIt, also or apply, and it'll be passed as the argument or the context of a scope function.

-
TypeScript
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
const person = {name: "Manuel", email: "ney.br.santos@gmail.com", age: 35};
-
-person.letIt(it => {
-    console.log(`${it.name},`);
-    it.age < 30 ? console.log("A Young Man") : console.log("An Old Man");
-    return it.age;
-}).also(it => {
-    console.log(`Actual Age is ${it}`);
-});
-// Output:
-//      Manuel,
-//      An Old Man
-//      Actual Age is 35
-
-

It also supports the use of the new Optional Chaining Operator, -bringing the logic of Kotlin's Null Safe Calls to the JavaScript world.

-
TypeScript
1
-2
-3
-4
-5
-6
-7
 const user = await this.userRepository.findOneBy({
-    id: userId,
-});
-
-user?.runIt(function() {
-    this.emailService.send(this.email, `${this.name} welcome to the Katxupa library`);
-});
-
-

You can execute a block of code only if a value is neither null nor undefined: -

TypeScript
1
-2
-3
const data: string | null = await getData();
-
-data?.also(it => console.log(`Already initialized: ${it}`)) ?? console.log("Still not initialized");
-
-The above code is equivalent to: -
TypeScript
1
-2
-3
-4
if (data != null && data != undefined)
-    console.log(`Already initialized: ${str!}`);
-else
-    console.log("Still not initialized");
-

-

The usage of takeIf & takeUnless is a bit different. You can call any value with takeIf and it will -return the caller instance if the predicate is true, or undefined if it's false (and vice versa when using takeUnless). -

TypeScript
1
-2
-3
-4
-5
-6
-7
const account = await accountService.getAccount(id);
-
-account.takeIf(it => {
-    return addressBook.has(it.email);
-})?.also(it => {
-    emailService.send(it.email, "You are entitled for crypto airdrop")
-}) ?? console.log(`Account with ${id} not found in the system`);
-

-

Null Safety#

-
    -
  • Null-safety through Optional Chaining Operator for scope functions: -
    TypeScript
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    -11
    -12
    -13
    -14
    -15
    // Only run the code block if "numberOrUndefined" is defined 
    -const numberOrUndefinedOrNull = await bitcoinService.getPrice();
    -numberOrUndefinedOrNull?.letIt((it) => {
    -    it++;
    -    it = it * 100;
    -    return it;
    -});
    -
    -// Actually, there is no need to declare a variable
    -(await bitcoinService.getPrice())
    -    ?.letIt((it) => {
    -        it++;
    -        it = it * 100;
    -        return it;
    -    });
    -
  • -
  • Optional wrapper for general purpose: -
    TypeScript
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    // Example 1
    -// Get Usecase:
    -//    1- Validate if user exists
    -//    2- Through an HttpError if not 
    -//    3- Return the user object
    -return optionalOf(user)
    -    .orElseThrow(() => new NotFoundError("User doesn't exist"))
    -    .get();
    -
    -// Example 2
    -// Delete Usecase:
    -//    1- Validate if user exists
    -//    2- Through an HttpError if not 
    -//    3-  Delete the user from the database asynchronously and await for the result
    -await Optional.of(user)
    -  .orElseThrow(() => new HttpError(409, "User doesn't exist"))
    -  .runAsync(() => this.userRepository.delete({id: userId}));
    -
    -// Example 3
    -// Update usecase:
    -//    1- Validate if user exists
    -//    2- Through an HttpError if not
    -//    3- If exists, merge the existing one with additional userData
    -//    4- Call the user repository and save the updated user asyncronously, returning a promise
    -//            
    -return optionalOf(user)
    -    .orElseThrow(() => new HttpError(409, "User doesn't exist"))
    -    .map(user => {
    -        return {
    -            ...user,
    -            userData,
    -        };
    -    })
    -    .runAsync(user => this.userRepository.save(user));
    -
  • -
-

Duration#

-

An easy, expressive and functional way of declaring a duration of time with support for various units (nanoseconds, -microseconds, milliseconds, seconds, minutes, hours, and days).

-
TypeScript
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
// Example 1
-durationOf(1000)
-    .toSeconds()
-    .letIt(it => {
-        console.log(`1000 milliseconds are the same as ${it} seconds`);
-    });
-
-// Example 2
-const oneYearInMinutes = (1).years().toHours().toMinutes();
-console.log(`1 year is approximately ${oneYearInMinutes} minutes.`);
-
-// Example 3
-const duration = (1).years().add((6).months()).toString();
-console.log(duration); // Output: 548d 0h 0m 0s 0ns
-
-

Range#

-

The Range class provides utility methods for working with numeric ranges.

-
TypeScript
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
// Example 1: Creating a Numeric Range
-const numericRange = Range.rangeTo(1, 5, 2);
-console.log(numericRange); // Output: [1, 3, 5]
-
-// Example 2: Creating a Numeric Range (Exclusive)
-const numericRangeAlias = rangeUntil(1, 5, 2);
-console.log(numericRangeAlias); // Output: [1, 3, 5]
-
-// Example 3: Checking if a Value is in Range
-const isInRange = Range.inRange(3, 1, 5);
-console.log(isInRange); // Output: true
-
-// Example 4: Range with chaining Operations 
-rangeTo(1, 5, 2)
-    .runIt(function () {
-        console.log(`multiplying the following range of numbers: ${this}`);
-        this.map(it => it * 2)
-            .forEach(it => console.log(it));
-    });
-
-

Global Utility Functions#

-

Global functions are the unsung heroes that transcend the boundaries of specific data types, providing a universal -toolkit for developers. These functions, residing in the global scope, are the go-to tools when you need versatile -and expressive solutions that operate seamlessly across various data structures.

-

Meet some Ingredients#

-
    -
  • runIt(): The maestro orchestrating the symphony of functions, runIt calls a specified function block and presents its harmonious result.
  • -
  • withIt(): The chameleon of functions, withIt transforms any object into the star of the show, letting it shine in a function block tailored just for them.
  • -
  • listOf(): Assemble an immutable list of elements effortlessly with listOf. It's your go-to for creating collections in a concise and readable manner.
  • -
  • mutableListOf(): When you need a dynamic collection that can evolve with your needs, turn to mutableListOf to create mutable lists with ease.
  • -
  • optionalOf(): Embrace the power of optionals with optionalOf, a function that lets you gracefully handle scenarios with potentially absent values.
  • -
  • durationOf(): Time is of the essence, and durationOf allows you to craft time durations with precision, making time manipulation a breeze.
  • -
  • sequenceOf(): Elevate your iteration game with sequenceOf, creating lazy sequences that conserve resources and provide on-the-fly transformation capabilities.
  • -
  • reducerOf(): Transform your data with reducerOf, a function designed for building reducers that streamline complex state transformations in a functional paradigm.
  • -
  • rangeTo(): Define ranges effortlessly with rangeTo, a function simplifying the creation of numeric ranges for iteration or data selection.
  • -
  • ok(): Indicate success with confidence using ok. This function constructs an "ok" result, signaling that a task or operation was completed successfully.
  • -
  • error(): Handle errors gracefully with error. This function constructs an error result, encapsulating details about the failure and allowing for structured error handling.
  • -
-

These are just a smell of the utility this library brings to the table. Please, check the complete list in the Global Functions section.

-

Type Extension Functions#

-

In JavaScript, where each data type carries its own set of behaviors, type extension functions emerge as the virtuosos of customization. -These functions enrich your interactions with core data types, injecting them with new capabilities, being functional -or utilities, and streamlining common operations.

- - - - - - - - - - - - - - - - - - - - - - - - - -
TypeUtilities
Object ExtensionsExtensions redefine how you interact with objects, enabling fluid and expressive operations tailored to your needs.
Number ExtensionsBrings a consistent, functional and powerful approach to numeric operations
String ExtensionsGive your strings a makeover with extensions that redefine the way you manipulate text.
Boolean ExtensionsFunctions like letIt, also, runIt, apply, takeIf, and takeUnless introduce a consistent and expressive way to handle boolean values.
- - - - - - -
-
- - -
- -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/site/index2/index.html b/site/index2/index.html deleted file mode 100644 index d4b620e..0000000 --- a/site/index2/index.html +++ /dev/null @@ -1,843 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Initializer Functions - Katxupa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Katxupa#

-

Delicious Dish for Typescript and JavaScript projects.

-

In Cape Verde we have a saying:

-

"Put a person to work in the field and serve them anything other than Katxupa -for breakfast, and you'll notice a decline in productivity and motivation. Therefore, give them Katxupa and spice it up on the side."

-

Just as "Katxupa" is an essential part of Cape Verdean culture, this library brings functional elements to enhance your -productivity and developer happiness. So, consume (use) it!

-
-

Katxupa, Cape Verde’s national dish, is a flavorful stew consisting of hominy, beans, seasoned meats, and vegetables. -Each family has its unique version, leading to delightful variations. -One undeniable fact: there is no Cape Verdean who doesn't appreciate Katxupa ("Cachupa") — whether for breakfast, lunch, dinner, or any time, anywhere.

-
-

Why Katxupa#

-

For starters, the "K" in Katxupa stands for Kotlin, which was the primary inspiration for this library. Drawing from the -functional programming paradigm of Kotlin and its concise yet expressive syntax, Katxupa aims to bring similar benefits -to Typescript and JavaScript developers.

-

What Makes Katxupa Special?#

-
    -
  • -

    Functional Delight: Katxupa introduces functional programming concepts to enhance your code's expressiveness and clarity.

    -
  • -
  • -

    Kotlin-Inspired Goodness: Leveraging lessons learned from Kotlin, Katxupa provides utilities and extensions that streamline your workflow.

    -
  • -
  • -

    Boosted Productivity: Enjoy a more productive development experience with Katxupa's utility classes, sequences, durations, and more.

    -
  • -
  • -

    Developer Happiness: Inspired by the joy of coding in Kotlin, Katxupa seeks to bring happiness to your TypeScript and JavaScript projects.

    -
  • -
-

Key Features#

-
    -
  • -

    Scope Functions: Kotlin-like scope functions, provides a set of functions to execute a block of code in the context of a given object: letIt, runIt, withIt, apply, and also.

    -
  • -
  • -

    Collections Functions: Kotlin-like functions for Arrays, Maps, and Sets: Apply concise and expressive operations on collections.

    -
  • -
  • -

    Sequences: Lazy sequences with a Kotlin-esque feel, providing a convenient way to work with iterable data.

    -
  • -
  • -

    Duration: A flexible and comprehensive time duration class with support for various units, offering better time handling.

    -
  • -
  • -

    Optional: A type that represents an optional value, helping to avoid null or undefined-related issues.

    -
  • -
  • -

    Result and Either: Functional constructs to handle success, errors, and alternate paths in a more expressive manner.

    -
  • -
  • -

    Inspired by Cape Verde: Infused with the spirit of Cape Verde and its cherished dish Katxupa, this library aims to add flavor to your coding experience.

    -
  • -
-

Get a Taste of Katxupa#

-

Explore the documentation and see how Katxupa can bring a delightful touch to your TypeScript and JavaScript projects. -From functional programming utilities to time handling and result handling, Katxupa is here to make your coding journey more enjoyable.

- - - - - - -
-
- - -
- -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/site/scope/index.html b/site/scope/index.html deleted file mode 100644 index 28e02f4..0000000 --- a/site/scope/index.html +++ /dev/null @@ -1,1262 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Scope Functions - Katxupa - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - -
-
-
- - - -
-
-
- - - -
-
-
- - - -
-
- - - - - - - -

Scope Functions

- -

Scope Functions#

-

The Katxupa library contains several functions whose sole purpose is to execute a block of code within the context of an object. -When you call such a function on an object with a lambda expression provided, it forms a temporary scope. In this scope, -you can access the object through it or in some cases this. Such functions are called scope functions.

-

There are five of them: letIt, runIt, withIt, applyIt, and alsoIt.

-

Basically, these functions all perform the same action: execute a block of code on an object. What's different is how this -object becomes available inside the block and what the result of the whole expression is.

-

Here's a typical example of how to use a scope function: -

TypeScript
1
-2
-3
-4
-5
-6
({name: "Manuel", age: 36})
-    .letIt(it => {
-        console.log(it);
-        it.age++;
-        console.log(it);
-    });
-
-If you write the same without letIt, you'll have to introduce a new variable and repeat its name whenever you use it. -
TypeScript
1
-2
-3
-4
const user = {name: "Manuel", age: 36};
-console.log(user);
-user.age++;
-console.log(user);
-

-

Scope functions don't introduce any new technical capabilities, but they can make your code more concise and readable.

-

Due to the many similarities between scope functions, choosing the right one for your use case can be tricky. -The choice mainly depends on your intent and the consistency of use in your project. Below, we provide detailed descriptions -of the differences between scope functions and their conventions.

-

Function selection#

-

To help you choose the right scope function for your purpose, we provide this table that summarizes the key differences between them.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionObject ReferenceReturn ValueIs extension function
letItitLambda ResultYes
runItthisLambda ResultYes
runIt-Lambda ResultNo: called without the context object
withItthisLambda ResultNo: takes the context object as an argument.
applyItthisContext ObjectYes
alsoItitContext ObjectYes
-
-

Note that letIt & alsoIt can be called with standard lambda/arrow functions, but because JavaScript arrow functions don't -have an own this context, runIt & applyIt have to be called with standard functions.

-
-

Detailed information about these functions is provided in the dedicated sections below.

-

Here is a short guide for choosing scope functions depending on the intended purpose: -* Executing a lambda on non-nullable objects: letIt -* Introducing an expression as a variable in local scope: letIt -* Object configuration: applyIt -* Object configuration and computing the result: runIt -* Running statements where an expression is required: non-extension runIt -* Additional effects: alsoIt -* Grouping function calls on an object: withIt

-

The use cases of different scope functions overlap, so you can choose which functions to use based on the specific -conventions used in your project or team.

-

Although scope functions can make your code more concise, avoid overusing them: it can make your code hard to read and -lead to errors. We also recommend that you avoid nesting scope functions and be careful when chaining them because it's -easy to get confused about the current context object and value of this or it.

-

Distinctions#

-

Because scope functions are similar in nature, it's important to understand the differences between them. There are two -main differences between each scope function:

-
    -
  • The way they refer to the context object.
  • -
  • Their return value.
  • -
-

Context object: this or it#

-

Inside the lambda passed to a scope function, the context object is available by a short reference instead of its actual name. -Each scope function uses one of two ways to reference the context object: as a function receiver (this) or as a lambda argument (it). -Both provide the same capabilities, so we describe the pros and cons of each for different use cases and provide recommendations for their use.

-
TypeScript
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
function main() {
-    const str = "Hello"
-    // this
-    str.runIt(function () {
-        console.log(`The string's length: ${this.length}`)
-    } );
-
-    // it
-    str.letIt(it => {
-        console.log(`The string's length: ${it.length}`)
-    })
-}
-
-

Functions#

-

To help you choose the right scope function for your use case, we describe them in detail and provide recommendations for use. -Technically, scope functions are interchangeable in many cases, so the examples show conventions for using them.

-

letIt#

-
    -
  • The context object is available as an argument (it).
  • -
  • The return value is the lambda result.
  • -
-

letIt can be used to invoke one or more functions on results of call chains. -

TypeScript
1
-2
-3
const data: Array<number> | null = await idsFromFile();
-
-const str = data?.letIt(it => convertToString(it)) ?? "empty";
-

-

withIt#

-
    -
  • The context object is available as a receiver (this).
  • -
  • The return value is the lambda result.
  • -
-

As withIt is not an extension function: the context object is passed as an argument, but inside the lambda, it's available as a receiver (this).

-

We recommend using withIt for calling functions on the context object when you don't need to use the returned result. -In code, with can be read as "with this object, do the following."

-
TypeScript
1
-2
-3
-4
-5
-6
const numbers = mutableListOf("one", "two", "three");
-
-withIt(numbers, function () {
-    console.log(`'withIt' is called with argument ${this}`);
-    console.log(`It contains ${this.length} elements`);
-});
-
-

You can also use withIt to introduce a helper object whose properties or functions are used for calculating a value. -

TypeScript
1
-2
-3
-4
-5
-6
const numbers = mutableListOf<string>("one", "two", "three");
-
-const firstAndLast = withIt(numbers, function () {
-    return `The first element is ${this.first()}, the last element is ${this.last()}`
-});
-console.debug(firstAndLast);
-

-

runIt#

-
    -
  • The context object is available as a receiver (this).
  • -
  • The return value is the lambda result.
  • -
-

runIt does the same as withIt but it is implemented as an extension function. So like letIt, you can call it on the context object using dot notation.

-

runIt is useful when your lambda function both initializes objects and computes the return value.

-
TypeScript
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
const service = new MultiportService("https://api.example.com/data", 80)
-
-const result = service.runIt(function () {
-    this.port = 8080;
-    const result = this.query(prepareRequest());
-    console.debug(`Request sent to port ${this.port}"`);
-    return result;
-});
-
-// the same code written with letIt() function:
-const letResult = service.letIt(it => {
-    it.port = 8080;
-    const result = it.query(prepareRequest());
-    console.debug(`Request sent to port ${it.port}"`);
-    return result;
-});
-
-

You can also invoke runIt as a non-extension function. The non-extension variant of runIt has no context object, but it still returns the lambda result. -Non-extension run lets you execute a block of several statements where an expression is required. -In code, non-extension runIt can be read as "run the code block and compute the result."

-
TypeScript
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
const hexNumberRegex = runIt(() => {
-    const digits = "0-9"
-    const hexDigits = "A-Fa-f"
-    const sign = "+-"
-
-   return  new RegExp(`[${sign}]?[${digits}${hexDigits}]+`, "g");
-});
-
-let match;
-while ((match = hexNumberRegex.exec("+123 -FFFF !%*& 88 XYZ")) !== null) {
-    console.log(match[0]);
-}
-
-

applyIt#

-
    -
  • The context object is available as a receiver (this).
  • -
  • The return value is the object itself.
  • -
-

As applyIt returns the context object itself, we recommend that you use it for code blocks that don't return a value and -that mainly operate on the members of the receiver object. The most common use case for applyIt is for object configuration. -Such calls can be read as "apply the following assignments to the object."

-

TypeScript
1
-2
-3
-4
-5
-6
-7
-8
const manuel = {name: "Manuel", age: 36};
-
-manuel.applyIt(function () {
-    this.name = "Manuel Santos";
-    this.age++;
-    (this as any)["country"] = "Portugal";
-});
-console.log(manuel)
-
-Another use case for applyIt is to include applyIt in multiple call chains for more complex processing.

-

alsoIt#

-
    -
  • The context object is available as an argument (it).
  • -
  • The return value is the object itself.
  • -
-

alsoIt is useful for performing some actions that take the context object as an argument. -Use alsoIt for actions that need a reference to the object rather than its properties and functions, or when you -don't want to shadow the this reference from an outer scope.

-

When you see also in code, you can read it as "and also do the following with the object."

-
TypeScript
1
-2
-3
-4
-5
const numbers = mutableListOf<string>("one", "two", "three");
-
-numbers
-    .alsoIt(it => console.log(`The list elements before adding new one: ${it}`))
-    .push("four");
-
-

takeIf and takeUnless#

-

In addition to scope functions, the Katxupa standard library contains the functions takeIf and takeUnless. -These functions let you embed checks of an object's state in call chains.

-

When called on an object along with a predicate, takeIf returns this object if it satisfies the given predicate. -Otherwise, it returns undefined. So, takeIf is a filtering function for a single object.

-

takeUnless has the opposite logic of takeIf. When called on an object along with a predicate, takeUnless returns -undefined if it satisfies the given predicate. Otherwise, it returns the object.

-

When using takeIf or takeUnless, the object is available as a lambda argument (it).

-
TypeScript
1
-2
-3
-4
-5
-6
const number: number = Math.floor(Math.random() * 100);
-
-const evenOrNull = number.takeIf(it =>  it % 2 == 0);
-const oddOrNull = number.takeUnless(it => it % 2 == 0);
-
-console.log(`even: ${evenOrNull}, odd: ${oddOrNull}`);
-
-
-

When chaining other functions after takeIf and takeUnless, don't forget to perform a null check or use a safe call (?.) because their return value is nullable.

-
-
TypeScript
1
-2
-3
-4
const str = "Hello";
-const caps = str.takeIf(it => it.length > 0)?.toUpperCase();
-//const caps = str.takeIf(it => it.length > 0).toUpperCase() //compilation error
-console.debug(caps);
-
-

takeIf and takeUnless are especially useful in combination with scope functions. For example, you can chain -takeIf and takeUnless with letIt to runIt a code block on objects that match the given predicate. To do this, -call takeIf on the object and then call let with a safe call (?). For objects that don't match the predicate, takeIf -returns undefined and letIt isn't invoked.

-
TypeScript
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
function displaySubstringPosition(input: string, sub: string) {
-    input.indexOf(sub)
-        .takeIf(it => it >= 0)
-        ?.letIt(it => {
-            console.log(`The substring ${sub} is found in ${input}.`)
-            console.log(`Its start position is ${it}.`)
-        });
-}
-
-displaySubstringPosition("010000011", "11");
-displaySubstringPosition("010000011", "12");
-
-// Output:
-//  The substring 11 is found in 010000011.
-//  Its start position is 7.
-
- - - - - - -
-
- - -
- -
- - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/site/search/search_index.json b/site/search/search_index.json deleted file mode 100644 index 36cd452..0000000 --- a/site/search/search_index.json +++ /dev/null @@ -1 +0,0 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Katxupa","text":"

Delicious Dish for Typescript and JavaScript projects.

In Cape Verde we have a saying:

\"Put a person to work in the field and serve them anything other than Katxupa for breakfast, and you'll notice a decline in productivity and motivation. Therefore, give them Katxupa and spice it up on the side.\"

Just as \"Katxupa\" is an essential part of Cape Verdean culture, this library brings functional elements to enhance your productivity and developer happiness. So, consume (use) it!

Katxupa, Cape Verde\u2019s national dish, is a flavorful stew consisting of hominy, beans, seasoned meats, and vegetables. Each family has its unique version, leading to delightful variations. One undeniable fact: there is no Cape Verdean who doesn't appreciate Katxupa (\"Cachupa\") \u2014 whether for breakfast, lunch, dinner, or any time, anywhere.

"},{"location":"#why_katxupa","title":"Why Katxupa","text":"

For starters, the \"K\" in Katxupa stands for Kotlin, which was the primary inspiration for this library. Drawing from the functional programming paradigm of Kotlin and its concise yet expressive syntax, Katxupa aims to bring similar benefits to Typescript and JavaScript developers.

"},{"location":"#what_makes_katxupa_special","title":"What Makes Katxupa Special?","text":"
  • Functional Delight: Katxupa introduces functional programming concepts to enhance your code's expressiveness and clarity.

  • Kotlin-Inspired Goodness: Leveraging lessons learned from Kotlin, Katxupa provides utilities and extensions that streamline your workflow.

  • Boosted Productivity: Enjoy a more productive development experience with Katxupa's utility classes, sequences, durations, and more.

  • Developer Happiness: Inspired by the joy of coding in Kotlin, Katxupa seeks to bring happiness to your TypeScript and JavaScript projects.

"},{"location":"#key_features","title":"Key Features","text":"
  • Scope Functions: Kotlin-like scope functions, provides a set of functions to execute a block of code in the context of a given object: letIt, runIt, withIt, apply, and also.

  • Collections Functions: Kotlin-like functions for Arrays, Maps, and Sets: Apply concise and expressive operations on collections.

  • Sequences: Lazy sequences with a Kotlin-esque feel, providing a convenient way to work with iterable data.

  • Duration: A flexible and comprehensive time duration class with support for various units, offering better time handling.

  • Optional: A type that represents an optional value, helping to avoid null or undefined-related issues.

  • Result and Either: Functional constructs to handle success, errors, and alternate paths in a more expressive manner.

  • Inspired by Cape Verde: Infused with the spirit of Cape Verde and its cherished dish Katxupa, this library aims to add flavor to your coding experience.

"},{"location":"#get_a_taste_of_katxupa","title":"Get a Taste of Katxupa","text":"

Explore the documentation and see how Katxupa can bring a delightful touch to your TypeScript and JavaScript projects. From functional programming utilities to time handling and result handling, Katxupa is here to make your coding journey more enjoyable.

"},{"location":"#installation","title":"Installation","text":"

This package is build up with simplicity in mind, brings no additional dependencies, and it's published in NPM https://www.npmjs.com/package/katxupa.

It can be installed using your preferred package manager.

"},{"location":"#npm","title":"NPM","text":"Bash
npm install katxupa\n
"},{"location":"#pnpm","title":"PNPM","text":"Bash
pnpm install katxupa\n
"},{"location":"#yarn","title":"YARN","text":"Bash
yarn add katxupa\n
"},{"location":"#usage","title":"Usage","text":""},{"location":"#scope_functions","title":"Scope Functions","text":"

Simply call any value with letIt, runIt, also or apply, and it'll be passed as the argument or the context of a scope function.

TypeScript
const person = {name: \"Manuel\", email: \"ney.br.santos@gmail.com\", age: 35};\nperson.letIt(it => {\nconsole.log(`${it.name},`);\nit.age < 30 ? console.log(\"A Young Man\") : console.log(\"An Old Man\");\nreturn it.age;\n}).also(it => {\nconsole.log(`Actual Age is ${it}`);\n});\n// Output:\n//      Manuel,\n//      An Old Man\n//      Actual Age is 35\n

It also supports the use of the new Optional Chaining Operator, bringing the logic of Kotlin's Null Safe Calls to the JavaScript world.

TypeScript
 const user = await this.userRepository.findOneBy({\nid: userId,\n});\nuser?.runIt(function() {\nthis.emailService.send(this.email, `${this.name} welcome to the Katxupa library`);\n});\n

You can execute a block of code only if a value is neither null nor undefined: TypeScript

const data: string | null = await getData();\ndata?.also(it => console.log(`Already initialized: ${it}`)) ?? console.log(\"Still not initialized\");\n
The above code is equivalent to: TypeScript
if (data != null && data != undefined)\nconsole.log(`Already initialized: ${str!}`);\nelse\nconsole.log(\"Still not initialized\");\n

The usage of takeIf & takeUnless is a bit different. You can call any value with takeIf and it will return the caller instance if the predicate is true, or undefined if it's false (and vice versa when using takeUnless). TypeScript

const account = await accountService.getAccount(id);\naccount.takeIf(it => {\nreturn addressBook.has(it.email);\n})?.also(it => {\nemailService.send(it.email, \"You are entitled for crypto airdrop\")\n}) ?? console.log(`Account with ${id} not found in the system`);\n

"},{"location":"#null_safety","title":"Null Safety","text":"
  • Null-safety through Optional Chaining Operator for scope functions: TypeScript
    // Only run the code block if \"numberOrUndefined\" is defined \nconst numberOrUndefinedOrNull = await bitcoinService.getPrice();\nnumberOrUndefinedOrNull?.letIt((it) => {\nit++;\nit = it * 100;\nreturn it;\n});\n// Actually, there is no need to declare a variable\n(await bitcoinService.getPrice())\n?.letIt((it) => {\nit++;\nit = it * 100;\nreturn it;\n});\n
  • Optional wrapper for general purpose: TypeScript
    // Example 1\n// Get Usecase:\n//    1- Validate if user exists\n//    2- Through an HttpError if not \n//    3- Return the user object\nreturn optionalOf(user)\n.orElseThrow(() => new NotFoundError(\"User doesn't exist\"))\n.get();\n// Example 2\n// Delete Usecase:\n//    1- Validate if user exists\n//    2- Through an HttpError if not \n//    3-  Delete the user from the database asynchronously and await for the result\nawait Optional.of(user)\n.orElseThrow(() => new HttpError(409, \"User doesn't exist\"))\n.runAsync(() => this.userRepository.delete({id: userId}));\n// Example 3\n// Update usecase:\n//    1- Validate if user exists\n//    2- Through an HttpError if not\n//    3- If exists, merge the existing one with additional userData\n//    4- Call the user repository and save the updated user asyncronously, returning a promise\n//            \nreturn optionalOf(user)\n.orElseThrow(() => new HttpError(409, \"User doesn't exist\"))\n.map(user => {\nreturn {\n...user,\nuserData,\n};\n})\n.runAsync(user => this.userRepository.save(user));\n
"},{"location":"#duration","title":"Duration","text":"

An easy, expressive and functional way of declaring a duration of time with support for various units (nanoseconds, microseconds, milliseconds, seconds, minutes, hours, and days).

TypeScript
// Example 1\ndurationOf(1000)\n.toSeconds()\n.letIt(it => {\nconsole.log(`1000 milliseconds are the same as ${it} seconds`);\n});\n// Example 2\nconst oneYearInMinutes = (1).years().toHours().toMinutes();\nconsole.log(`1 year is approximately ${oneYearInMinutes} minutes.`);\n// Example 3\nconst duration = (1).years().add((6).months()).toString();\nconsole.log(duration); // Output: 548d 0h 0m 0s 0ns\n
"},{"location":"#range","title":"Range","text":"

The Range class provides utility methods for working with numeric ranges.

TypeScript
// Example 1: Creating a Numeric Range\nconst numericRange = Range.rangeTo(1, 5, 2);\nconsole.log(numericRange); // Output: [1, 3, 5]\n// Example 2: Creating a Numeric Range (Exclusive)\nconst numericRangeAlias = rangeUntil(1, 5, 2);\nconsole.log(numericRangeAlias); // Output: [1, 3, 5]\n// Example 3: Checking if a Value is in Range\nconst isInRange = Range.inRange(3, 1, 5);\nconsole.log(isInRange); // Output: true\n// Example 4: Range with chaining Operations \nrangeTo(1, 5, 2)\n.runIt(function () {\nconsole.log(`multiplying the following range of numbers: ${this}`);\nthis.map(it => it * 2)\n.forEach(it => console.log(it));\n});\n
"},{"location":"#global_utility_functions","title":"Global Utility Functions","text":"

Global functions are the unsung heroes that transcend the boundaries of specific data types, providing a universal toolkit for developers. These functions, residing in the global scope, are the go-to tools when you need versatile and expressive solutions that operate seamlessly across various data structures.

"},{"location":"#meet_some_ingredients","title":"Meet some Ingredients","text":"
  • runIt(): The maestro orchestrating the symphony of functions, runIt calls a specified function block and presents its harmonious result.
  • withIt(): The chameleon of functions, withIt transforms any object into the star of the show, letting it shine in a function block tailored just for them.
  • listOf(): Assemble an immutable list of elements effortlessly with listOf. It's your go-to for creating collections in a concise and readable manner.
  • mutableListOf(): When you need a dynamic collection that can evolve with your needs, turn to mutableListOf to create mutable lists with ease.
  • optionalOf(): Embrace the power of optionals with optionalOf, a function that lets you gracefully handle scenarios with potentially absent values.
  • durationOf(): Time is of the essence, and durationOf allows you to craft time durations with precision, making time manipulation a breeze.
  • sequenceOf(): Elevate your iteration game with sequenceOf, creating lazy sequences that conserve resources and provide on-the-fly transformation capabilities.
  • reducerOf(): Transform your data with reducerOf, a function designed for building reducers that streamline complex state transformations in a functional paradigm.
  • rangeTo(): Define ranges effortlessly with rangeTo, a function simplifying the creation of numeric ranges for iteration or data selection.
  • ok(): Indicate success with confidence using ok. This function constructs an \"ok\" result, signaling that a task or operation was completed successfully.
  • error(): Handle errors gracefully with error. This function constructs an error result, encapsulating details about the failure and allowing for structured error handling.

These are just a smell of the utility this library brings to the table. Please, check the complete list in the Global Functions section.

"},{"location":"#type_extension_functions","title":"Type Extension Functions","text":"

In JavaScript, where each data type carries its own set of behaviors, type extension functions emerge as the virtuosos of customization. These functions enrich your interactions with core data types, injecting them with new capabilities, being functional or utilities, and streamlining common operations.

Type Utilities Object Extensions Extensions redefine how you interact with objects, enabling fluid and expressive operations tailored to your needs. Number Extensions Brings a consistent, functional and powerful approach to numeric operations String Extensions Give your strings a makeover with extensions that redefine the way you manipulate text. Boolean Extensions Functions like letIt, also, runIt, apply, takeIf, and takeUnless introduce a consistent and expressive way to handle boolean values."},{"location":"array/","title":"Array","text":"Markdown
---\nid: array\ntitle: Array Component\nsidebar_label: Array\n---\n## Introduction\nThe Array component in the Katxupa library provides additional utility functions for working with arrays.\n\n### Installation\nTo use the Array component, you can include it in your project:\n\n```bash\nnpm install katxupa\n
"},{"location":"array/#usage","title":"Usage","text":""},{"location":"array/#listof","title":"listOf","text":"

Creates an immutable list from the provided elements.

JavaScript
const list = listOf(1, 2, 3);\n// list is [1, 2, 3]\n
"},{"location":"array/#mutablelistof","title":"mutableListOf","text":"

Creates a mutable list from the provided elements.

JavaScript
const mutableList = mutableListOf(1, 2, 3);\n// mutableList is [1, 2, 3]\n
"},{"location":"array/#emptylist","title":"emptyList","text":"

Creates an empty list.

JavaScript
const empty = emptyList();\n// empty is []\n
"},{"location":"array/#associatewith","title":"associateWith","text":"

Associates each element with a key-value pair based on the provided selectors.

JavaScript
const elements = [\n{ id: 1, value: 'a' },\n{ id: 2, value: 'b' },\n];\nconst keyValuePairs = elements.associateWith(\n(element) => element.id,\n(element) => element.value\n);\n// keyValuePairs is { '1': 'a', '2': 'b' }\n
"},{"location":"array/#mapindexed","title":"mapIndexed","text":"

Maps each element to a new value using the provided transformation function.

JavaScript
const numbers = [1, 2, 3];\nconst squaredNumbers = numbers.mapIndexed((num, index) => num * num + index);\n// squaredNumbers is [1, 5, 11]\n
"},{"location":"array/#sortdescending","title":"sortDescending","text":"

Sorts the collection in descending order.

JavaScript
const numbers = [3, 1, 4, 1, 5, 9, 2];\nconst sortedNumbers = numbers.sortDescending();\n// sortedNumbers is [9, 5, 4, 3, 2, 1, 1]\n
"},{"location":"array/#sortby","title":"sortBy","text":"

Sorts the collection using the provided comparator function.

JavaScript
const users = [\n{ name: 'John', age: 30 },\n{ name: 'Alice', age: 25 },\n{ name: 'Bob', age: 35 },\n];\nconst sortedUsers = users.sortBy((a, b) => a.age - b.age);\n// sortedUsers is [{ name: 'Alice', age: 25 }, { name: 'John', age: 30 }, { name: 'Bob', age: 35 }]\n
"},{"location":"array/#plus","title":"plus","text":"

Concatenates the collection with another array.

JavaScript
const collection = [1, 2, 3];\nconst otherArray = [4, 5, 6];\nconst result = collection.plus(otherArray);\n// result is [1, 2, 3, 4, 5, 6]\n
"},{"location":"array/#minus","title":"minus","text":"

Removes elements from the collection that are present in another array.

JavaScript
const collection = [1, 2, 3, 4, 5];\nconst elementsToRemove = [3, 5];\nconst result = collection.minus(elementsToRemove);\n// result is [1, 2, 4]\n
"},{"location":"array/#minusassign","title":"minusAssign","text":"

Removes elements from the collection that are present in another array (mutates the collection).

JavaScript
const collection = [1, 2, 3, 4, 5];\nconst elementsToRemove = [3, 5];\ncollection.minusAssign(elementsToRemove);\n// collection is now [1, 2, 4]\n
"},{"location":"array/#plusassign","title":"plusAssign","text":"

Appends elements from another array to the collection (mutates the collection).

JavaScript
const collection = [1, 2, 3];\nconst additionalElements = [4, 5, 6];\ncollection.plusAssign(additionalElements);\n// collection is now [1, 2, 3, 4, 5, 6]\n
"},{"location":"array/#count","title":"count","text":"

Returns the number of elements in the collection.

JavaScript
const collection = [1, 2, 3, 4, 5];\nconst count = collection.count();\n// count is 5\n
"},{"location":"array/#removeall","title":"removeAll","text":"

Removes elements from the collection based on a predicate or a collection of elements.

JavaScript
const collection = [1, 2, 3, 4, 5];\nconst elementsToRemove = [3, 5];\nconst result = collection.removeAll(elementsToRemove);\n// result is [1, 2, 4]\n
"},{"location":"array/#retainall","title":"retainAll","text":"

Retains only the elements in the collection that are present in another array.

JavaScript
const collection = [1, 2, 3, 4, 5];\nconst elementsToRetain = [3, 5];\nconst result = collection.retainAll(elementsToRetain);\n// result is [3, 5]\n
"},{"location":"array/#last","title":"last","text":"

Returns the last element in the collection.

JavaScript
const collection = [1, 2, 3];\nconst lastElement = collection.last();\n// lastElement is 3\n
"},{"location":"array/#getorelse","title":"getOrElse","text":"

Gets the element at the specified index or provides a default value if the index is out of bounds.

JavaScript
const collection = [1, 2, 3, 4, 5];\nconst element = collection.getOrElse(2, () => 10);\n// element is 3\n
"},{"location":"array/#getorempty","title":"getOrEmpty","text":"

Gets an optional containing the element at the specified index.

JavaScript
const collection = [1, 2, 3, 4, 5];\nconst optionalElement = collection.getOrEmpty(2);\n// optionalElement contains the value Optional.of(3)\n
"},{"location":"array/#shuffle","title":"shuffle","text":"

Shuffles the elements in the collection randomly.

JavaScript
const collection = [1, 2, 3, 4, 5];\ncollection.shuffle();\n// collection is now shuffled randomly, e.g., [3, 1, 5, 2, 4]\n
"},{"location":"array/#api_reference","title":"API Reference","text":""},{"location":"array/#methods","title":"Methods","text":"
  • associateWith
  • mapIndexed
  • sortDescending
  • sortBy
  • plus
  • minus
  • minusAssign
  • plusAssign
  • count
  • removeAll
  • retainAll
  • last
  • getOrElse
  • getOrEmpty
  • shuffle
"},{"location":"array/#associatewith_1","title":"associateWith","text":"

Associates each element with a key-value pair based on the provided selectors.

"},{"location":"array/#parameters","title":"Parameters","text":"
  • keySelector: (element: T) => K - The function to extract keys from elements.
  • valueSelector: (element: T) => V - The function to extract values from elements.
"},{"location":"array/#returns","title":"Returns","text":"

A record associating keys with their corresponding values.

"},{"location":"array/#example","title":"Example","text":"JavaScript
const elements = [\n{ id: 1, value: 'a' },\n{ id: 2, value: 'b' },\n];\nconst keyValuePairs = elements.associateWith(\n(element) => element.id,\n(element) => element.value\n);\n// keyValuePairs is { '1': 'a', '2': 'b' }\n
"},{"location":"array/#mapindexed_1","title":"mapIndexed","text":"

Maps each element to a new value using the provided transformation function.

"},{"location":"array/#parameters_1","title":"Parameters","text":"
  • transform: (element: T, index: number) => U - The function to transform each element.
"},{"location":"array/#returns_1","title":"Returns","text":"

A readonly array containing the transformed elements.

"},{"location":"array/#example_1","title":"Example","text":"JavaScript
const numbers = [1, 2, 3];\nconst squaredNumbers = numbers.mapIndexed((num, index) => num * num + index);\n// squaredNumbers is [1, 5, 11]\n
"},{"location":"array/#sortdescending_1","title":"sortDescending","text":"

Sorts the collection in descending order.

"},{"location":"array/#returns_2","title":"Returns","text":"

A reference to the sorted array.

"},{"location":"array/#example_2","title":"Example","text":"JavaScript
const numbers = [3, 1, 4, 1, 5, 9, 2];\nnumbers.sortDescending();\n// numbers is now [9, 5, 4, 3, 2, 1, 1]\n
"},{"location":"array/#sortby_1","title":"sortBy","text":"

Sorts the collection using the provided comparator function.

"},{"location":"array/#parameters_2","title":"Parameters","text":"
  • comparator: (a: T, b: T) => number - The function to compare elements.
"},{"location":"array/#returns_3","title":"Returns","text":"

A reference to the sorted array.

"},{"location":"array/#example_3","title":"Example","text":"JavaScript
const users = [\n{ name: 'John', age: 30 },\n{ name: 'Alice', age: 25 },\n{ name: 'Bob', age: 35 },\n];\nusers.sortBy((a, b) => a.age - b.age);\n// users is now sorted by age: [{ name: 'Alice', age: 25 }, { name: 'John', age: 30 }, { name: 'Bob', age: 35 }]\n
"},{"location":"array/#plus_1","title":"plus","text":"

Concatenates the collection with another array.

"},{"location":"array/#parameters_3","title":"Parameters","text":"
  • other: T[] - The array to concatenate with the current collection.
"},{"location":"array/#returns_4","title":"Returns","text":"

A new array containing elements from both the current collection and the provided array.

"},{"location":"array/#example_4","title":"Example","text":"JavaScript
const collection = [1, 2, 3];\nconst otherArray = [4, 5, 6];\nconst result = collection.plus(otherArray);\n// result is [1, 2, 3, 4, 5, 6]\n
"},{"location":"array/#minus_1","title":"minus","text":"

Removes elements from the collection that are present in another array.

"},{"location":"array/#parameters_4","title":"Parameters","text":"
  • other: T[] - The array containing elements to be removed from the current collection.
"},{"location":"array/#returns_5","title":"Returns","text":"

A new array with elements not present in the provided array.

"},{"location":"array/#example_5","title":"Example","text":"JavaScript
const collection = [1, 2, 3, 4, 5];\nconst elementsToRemove = [3, 5];\nconst result = collection.minus(elementsToRemove);\n// result is [1, 2, 4]\n
"},{"location":"array/#minusassign_1","title":"minusAssign","text":"

Removes elements from the collection that are present in another array (mutates the collection).

"},{"location":"array/#parameters_5","title":"Parameters","text":"
  • collection: T[] - The array containing elements to be removed from the current collection.
"},{"location":"array/#returns_6","title":"Returns","text":"

A reference to the affected array.

"},{"location":"array/#example_6","title":"Example","text":"JavaScript
const collection = [1, 2, 3, 4, 5];\nconst elementsToRemove = [3, 5];\ncollection.minusAssign(elementsToRemove);\n// collection is now [1, 2, 4]\n
"},{"location":"array/#plusassign_1","title":"plusAssign","text":"

Appends elements from another array to the collection (mutates the collection).

"},{"location":"array/#parameters_6","title":"Parameters","text":"
  • other: T[] - The array containing elements to be added to the current collection.
"},{"location":"array/#returns_7","title":"Returns","text":"

A reference to the affected array.

"},{"location":"array/#example_7","title":"Example","text":"JavaScript
const collection = [1, 2, 3];\nconst additionalElements = [4, 5, 6];\ncollection.plusAssign(additionalElements);\n// collection is now [1, 2, 3, 4, 5, 6]\n
"},{"location":"array/#count_1","title":"count","text":"

Returns the number of elements in the collection.

"},{"location":"array/#returns_8","title":"Returns","text":"

The number of elements in the collection.

"},{"location":"array/#example_8","title":"Example","text":"JavaScript
const collection = [1, 2, 3, 4, 5];\nconst count = collection.count();\n// count is 5\n
"},{"location":"array/#removeall_1","title":"removeAll","text":"

Removes elements from the collection based on a predicate or a collection of elements.

"},{"location":"array/#parameters_7","title":"Parameters","text":"
  • predicate: ((item: T) => boolean) | T[] - The predicate function or collection of elements to remove.
"},{"location":"array/#returns_9","title":"Returns","text":"

A new array with elements removed based on the provided predicate or collection.

"},{"location":"array/#example_9","title":"Example","text":"JavaScript
const collection = [1, 2, 3, 4, 5];\nconst elementsToRemove = [3, 5];\nconst result = collection.removeAll(elementsToRemove);\n// result is [1, 2, 4]\n
"},{"location":"array/#retainall_1","title":"retainAll","text":"

Retains only the elements in the collection that are present in another array.

"},{"location":"array/#parameters_8","title":"Parameters","text":"
  • predicate: ((item: T) => boolean) | T[] - The predicate function or collection of elements to retain.
"},{"location":"array/#returns_10","title":"Returns","text":"

A new array containing only the elements that satisfy the provided predicate or are present in the provided collection.

"},{"location":"array/#example_10","title":"Example","text":"JavaScript
const collection = [1, 2, 3, 4, 5];\nconst elementsToRetain = [3, 5];\nconst result = collection.retainAll(elementsToRetain);\n// result is [3, 5]\n
"},{"location":"array/#last_1","title":"last","text":"

Returns the last element in the collection.

"},{"location":"array/#returns_11","title":"Returns","text":"

The last element in the collection.

"},{"location":"array/#throws","title":"Throws","text":"
  • NoSuchElementError - If the collection is empty.
"},{"location":"array/#example_11","title":"Example","text":"JavaScript
const collection = [1, 2, 3];\nconst lastElement = collection.last();\n// lastElement is 3\n
"},{"location":"array/#getorelse_1","title":"getOrElse","text":"

Gets the element at the specified index or provides a default value if the index is out of bounds.

"},{"location":"array/#parameters_9","title":"Parameters","text":"
  • index: number - The index of the element to retrieve.
  • defaultValueProvider: () => T - A function providing the default value.
"},{"location":"array/#returns_12","title":"Returns","text":"

The element at the specified index or the default value if the index is out of bounds.

"},{"location":"array/#example_12","title":"Example","text":"JavaScript
const collection = [1, 2, 3, 4, 5];\nconst element = collection.getOrElse(2, () => 10);\n// element is 3\n
"},{"location":"array/#getorempty_1","title":"getOrEmpty","text":"

Gets an optional containing the element at the specified index.

"},{"location":"array/#parameters_10","title":"Parameters","text":"
  • index: number - The index of the element.
"},{"location":"array/#returns_13","title":"Returns","text":"

An optional containing the element if it exists, otherwise an empty optional.

"},{"location":"array/#example_13","title":"Example","text":"JavaScript
const collection = [1, 2, 3, 4, 5];\nconst optionalElement = collection.getOrEmpty(2);\n// optionalElement contains the value Optional.of(3)\n
"},{"location":"array/#shuffle_1","title":"shuffle","text":"

Shuffles the elements in the collection randomly.

"},{"location":"array/#returns_14","title":"Returns","text":"

A reference to the affected array.

"},{"location":"array/#example_14","title":"Example","text":"

```javascript const collection = [1, 2, 3, 4, 5]; collection.shuffle(); // collection is now shuffled randomly, e.g., [3, 1, 5, 2, 4]

"},{"location":"index2/","title":"Katxupa","text":"

Delicious Dish for Typescript and JavaScript projects.

In Cape Verde we have a saying:

\"Put a person to work in the field and serve them anything other than Katxupa for breakfast, and you'll notice a decline in productivity and motivation. Therefore, give them Katxupa and spice it up on the side.\"

Just as \"Katxupa\" is an essential part of Cape Verdean culture, this library brings functional elements to enhance your productivity and developer happiness. So, consume (use) it!

Katxupa, Cape Verde\u2019s national dish, is a flavorful stew consisting of hominy, beans, seasoned meats, and vegetables. Each family has its unique version, leading to delightful variations. One undeniable fact: there is no Cape Verdean who doesn't appreciate Katxupa (\"Cachupa\") \u2014 whether for breakfast, lunch, dinner, or any time, anywhere.

"},{"location":"index2/#why_katxupa","title":"Why Katxupa","text":"

For starters, the \"K\" in Katxupa stands for Kotlin, which was the primary inspiration for this library. Drawing from the functional programming paradigm of Kotlin and its concise yet expressive syntax, Katxupa aims to bring similar benefits to Typescript and JavaScript developers.

"},{"location":"index2/#what_makes_katxupa_special","title":"What Makes Katxupa Special?","text":"
  • Functional Delight: Katxupa introduces functional programming concepts to enhance your code's expressiveness and clarity.

  • Kotlin-Inspired Goodness: Leveraging lessons learned from Kotlin, Katxupa provides utilities and extensions that streamline your workflow.

  • Boosted Productivity: Enjoy a more productive development experience with Katxupa's utility classes, sequences, durations, and more.

  • Developer Happiness: Inspired by the joy of coding in Kotlin, Katxupa seeks to bring happiness to your TypeScript and JavaScript projects.

"},{"location":"index2/#key_features","title":"Key Features","text":"
  • Scope Functions: Kotlin-like scope functions, provides a set of functions to execute a block of code in the context of a given object: letIt, runIt, withIt, apply, and also.

  • Collections Functions: Kotlin-like functions for Arrays, Maps, and Sets: Apply concise and expressive operations on collections.

  • Sequences: Lazy sequences with a Kotlin-esque feel, providing a convenient way to work with iterable data.

  • Duration: A flexible and comprehensive time duration class with support for various units, offering better time handling.

  • Optional: A type that represents an optional value, helping to avoid null or undefined-related issues.

  • Result and Either: Functional constructs to handle success, errors, and alternate paths in a more expressive manner.

  • Inspired by Cape Verde: Infused with the spirit of Cape Verde and its cherished dish Katxupa, this library aims to add flavor to your coding experience.

"},{"location":"index2/#get_a_taste_of_katxupa","title":"Get a Taste of Katxupa","text":"

Explore the documentation and see how Katxupa can bring a delightful touch to your TypeScript and JavaScript projects. From functional programming utilities to time handling and result handling, Katxupa is here to make your coding journey more enjoyable.

"},{"location":"scope/","title":"Scope Functions","text":""},{"location":"scope/#scope_functions","title":"Scope Functions","text":"

The Katxupa library contains several functions whose sole purpose is to execute a block of code within the context of an object. When you call such a function on an object with a lambda expression provided, it forms a temporary scope. In this scope, you can access the object through it or in some cases this. Such functions are called scope functions.

There are five of them: letIt, runIt, withIt, applyIt, and alsoIt.

Basically, these functions all perform the same action: execute a block of code on an object. What's different is how this object becomes available inside the block and what the result of the whole expression is.

Here's a typical example of how to use a scope function: TypeScript

({name: \"Manuel\", age: 36})\n.letIt(it => {\nconsole.log(it);\nit.age++;\nconsole.log(it);\n});\n
If you write the same without letIt, you'll have to introduce a new variable and repeat its name whenever you use it. TypeScript
const user = {name: \"Manuel\", age: 36};\nconsole.log(user);\nuser.age++;\nconsole.log(user);\n

Scope functions don't introduce any new technical capabilities, but they can make your code more concise and readable.

Due to the many similarities between scope functions, choosing the right one for your use case can be tricky. The choice mainly depends on your intent and the consistency of use in your project. Below, we provide detailed descriptions of the differences between scope functions and their conventions.

"},{"location":"scope/#function_selection","title":"Function selection","text":"

To help you choose the right scope function for your purpose, we provide this table that summarizes the key differences between them.

Function Object Reference Return Value Is extension function letIt it Lambda Result Yes runIt this Lambda Result Yes runIt - Lambda Result No: called without the context object withIt this Lambda Result No: takes the context object as an argument. applyIt this Context Object Yes alsoIt it Context Object Yes

Note that letIt & alsoIt can be called with standard lambda/arrow functions, but because JavaScript arrow functions don't have an own this context, runIt & applyIt have to be called with standard functions.

Detailed information about these functions is provided in the dedicated sections below.

Here is a short guide for choosing scope functions depending on the intended purpose: * Executing a lambda on non-nullable objects: letIt * Introducing an expression as a variable in local scope: letIt * Object configuration: applyIt * Object configuration and computing the result: runIt * Running statements where an expression is required: non-extension runIt * Additional effects: alsoIt * Grouping function calls on an object: withIt

The use cases of different scope functions overlap, so you can choose which functions to use based on the specific conventions used in your project or team.

Although scope functions can make your code more concise, avoid overusing them: it can make your code hard to read and lead to errors. We also recommend that you avoid nesting scope functions and be careful when chaining them because it's easy to get confused about the current context object and value of this or it.

"},{"location":"scope/#distinctions","title":"Distinctions","text":"

Because scope functions are similar in nature, it's important to understand the differences between them. There are two main differences between each scope function:

  • The way they refer to the context object.
  • Their return value.
"},{"location":"scope/#context_object_this_or_it","title":"Context object: this or it","text":"

Inside the lambda passed to a scope function, the context object is available by a short reference instead of its actual name. Each scope function uses one of two ways to reference the context object: as a function receiver (this) or as a lambda argument (it). Both provide the same capabilities, so we describe the pros and cons of each for different use cases and provide recommendations for their use.

TypeScript
function main() {\nconst str = \"Hello\"\n// this\nstr.runIt(function () {\nconsole.log(`The string's length: ${this.length}`)\n} );\n// it\nstr.letIt(it => {\nconsole.log(`The string's length: ${it.length}`)\n})\n}\n
"},{"location":"scope/#functions","title":"Functions","text":"

To help you choose the right scope function for your use case, we describe them in detail and provide recommendations for use. Technically, scope functions are interchangeable in many cases, so the examples show conventions for using them.

"},{"location":"scope/#letit","title":"letIt","text":"
  • The context object is available as an argument (it).
  • The return value is the lambda result.

letIt can be used to invoke one or more functions on results of call chains. TypeScript

const data: Array<number> | null = await idsFromFile();\nconst str = data?.letIt(it => convertToString(it)) ?? \"empty\";\n

"},{"location":"scope/#withit","title":"withIt","text":"
  • The context object is available as a receiver (this).
  • The return value is the lambda result.

As withIt is not an extension function: the context object is passed as an argument, but inside the lambda, it's available as a receiver (this).

We recommend using withIt for calling functions on the context object when you don't need to use the returned result. In code, with can be read as \"with this object, do the following.\"

TypeScript
const numbers = mutableListOf(\"one\", \"two\", \"three\");\nwithIt(numbers, function () {\nconsole.log(`'withIt' is called with argument ${this}`);\nconsole.log(`It contains ${this.length} elements`);\n});\n

You can also use withIt to introduce a helper object whose properties or functions are used for calculating a value. TypeScript

const numbers = mutableListOf<string>(\"one\", \"two\", \"three\");\nconst firstAndLast = withIt(numbers, function () {\nreturn `The first element is ${this.first()}, the last element is ${this.last()}`\n});\nconsole.debug(firstAndLast);\n

"},{"location":"scope/#runit","title":"runIt","text":"
  • The context object is available as a receiver (this).
  • The return value is the lambda result.

runIt does the same as withIt but it is implemented as an extension function. So like letIt, you can call it on the context object using dot notation.

runIt is useful when your lambda function both initializes objects and computes the return value.

TypeScript
const service = new MultiportService(\"https://api.example.com/data\", 80)\nconst result = service.runIt(function () {\nthis.port = 8080;\nconst result = this.query(prepareRequest());\nconsole.debug(`Request sent to port ${this.port}\"`);\nreturn result;\n});\n// the same code written with letIt() function:\nconst letResult = service.letIt(it => {\nit.port = 8080;\nconst result = it.query(prepareRequest());\nconsole.debug(`Request sent to port ${it.port}\"`);\nreturn result;\n});\n

You can also invoke runIt as a non-extension function. The non-extension variant of runIt has no context object, but it still returns the lambda result. Non-extension run lets you execute a block of several statements where an expression is required. In code, non-extension runIt can be read as \"run the code block and compute the result.\"

TypeScript
const hexNumberRegex = runIt(() => {\nconst digits = \"0-9\"\nconst hexDigits = \"A-Fa-f\"\nconst sign = \"+-\"\nreturn  new RegExp(`[${sign}]?[${digits}${hexDigits}]+`, \"g\");\n});\nlet match;\nwhile ((match = hexNumberRegex.exec(\"+123 -FFFF !%*& 88 XYZ\")) !== null) {\nconsole.log(match[0]);\n}\n
"},{"location":"scope/#applyit","title":"applyIt","text":"
  • The context object is available as a receiver (this).
  • The return value is the object itself.

As applyIt returns the context object itself, we recommend that you use it for code blocks that don't return a value and that mainly operate on the members of the receiver object. The most common use case for applyIt is for object configuration. Such calls can be read as \"apply the following assignments to the object.\"

TypeScript

const manuel = {name: \"Manuel\", age: 36};\nmanuel.applyIt(function () {\nthis.name = \"Manuel Santos\";\nthis.age++;\n(this as any)[\"country\"] = \"Portugal\";\n});\nconsole.log(manuel)\n
Another use case for applyIt is to include applyIt in multiple call chains for more complex processing.

"},{"location":"scope/#alsoit","title":"alsoIt","text":"
  • The context object is available as an argument (it).
  • The return value is the object itself.

alsoIt is useful for performing some actions that take the context object as an argument. Use alsoIt for actions that need a reference to the object rather than its properties and functions, or when you don't want to shadow the this reference from an outer scope.

When you see also in code, you can read it as \"and also do the following with the object.\"

TypeScript
const numbers = mutableListOf<string>(\"one\", \"two\", \"three\");\nnumbers\n.alsoIt(it => console.log(`The list elements before adding new one: ${it}`))\n.push(\"four\");\n
"},{"location":"scope/#takeif_and_takeunless","title":"takeIf and takeUnless","text":"

In addition to scope functions, the Katxupa standard library contains the functions takeIf and takeUnless. These functions let you embed checks of an object's state in call chains.

When called on an object along with a predicate, takeIf returns this object if it satisfies the given predicate. Otherwise, it returns undefined. So, takeIf is a filtering function for a single object.

takeUnless has the opposite logic of takeIf. When called on an object along with a predicate, takeUnless returns undefined if it satisfies the given predicate. Otherwise, it returns the object.

When using takeIf or takeUnless, the object is available as a lambda argument (it).

TypeScript
const number: number = Math.floor(Math.random() * 100);\nconst evenOrNull = number.takeIf(it =>  it % 2 == 0);\nconst oddOrNull = number.takeUnless(it => it % 2 == 0);\nconsole.log(`even: ${evenOrNull}, odd: ${oddOrNull}`);\n

When chaining other functions after takeIf and takeUnless, don't forget to perform a null check or use a safe call (?.) because their return value is nullable.

TypeScript
const str = \"Hello\";\nconst caps = str.takeIf(it => it.length > 0)?.toUpperCase();\n//const caps = str.takeIf(it => it.length > 0).toUpperCase() //compilation error\nconsole.debug(caps);\n

takeIf and takeUnless are especially useful in combination with scope functions. For example, you can chain takeIf and takeUnless with letIt to runIt a code block on objects that match the given predicate. To do this, call takeIf on the object and then call let with a safe call (?). For objects that don't match the predicate, takeIf returns undefined and letIt isn't invoked.

TypeScript
function displaySubstringPosition(input: string, sub: string) {\ninput.indexOf(sub)\n.takeIf(it => it >= 0)\n?.letIt(it => {\nconsole.log(`The substring ${sub} is found in ${input}.`)\nconsole.log(`Its start position is ${it}.`)\n});\n}\ndisplaySubstringPosition(\"010000011\", \"11\");\ndisplaySubstringPosition(\"010000011\", \"12\");\n// Output:\n//  The substring 11 is found in 010000011.\n//  Its start position is 7.\n
"}]} \ No newline at end of file diff --git a/site/sitemap.xml b/site/sitemap.xml deleted file mode 100644 index 6d84bca..0000000 --- a/site/sitemap.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - https://manusant.github.io/Katxupa/ - 2024-02-12 - daily - - - https://manusant.github.io/Katxupa/array/ - 2024-02-12 - daily - - - https://manusant.github.io/Katxupa/index2/ - 2024-02-12 - daily - - - https://manusant.github.io/Katxupa/scope/ - 2024-02-12 - daily - - \ No newline at end of file diff --git a/site/sitemap.xml.gz b/site/sitemap.xml.gz deleted file mode 100644 index b5de3e2..0000000 Binary files a/site/sitemap.xml.gz and /dev/null differ