mauss
Version:
lightweight, modular, type-safe utilities
995 lines (967 loc) • 44.8 kB
TypeScript
declare module 'mauss' {
type Currying<Fun extends AnyFunction> = <Arguments extends Progressive<Parameters<Fun>>>(...args: Arguments) => Arguments['length'] extends Parameters<Fun>['length'] ? ReturnType<Fun> : Currying<(...args: Slice<Parameters<Fun>, Arguments['length']>) => ReturnType<Fun>>;
/**
* A type-safe higher-order function that accepts a function with one or more parameters and returns a function that can take in one or more arguments with a max of the parameters length.
* If the total arguments provided has not yet reached the initial function parameters length, it will return a function until all the required parameters are fulfilled.
*
* @returns a curried function to take in the arguments
*/
export function curry<F extends AnyFunction>(fn: F, expected?: number): Currying<F>;
type Validator<Functions extends UnaryFunction[], Computed extends UnaryFunction = (v: ReturnType<Functions[0]>) => ReturnType<Functions[1]>> = Functions extends [infer Resolved, infer _, ...infer Rest] ? Rest extends UnaryFunction[] ? [Resolved, ...Validator<[Computed, ...Rest]>] : never : Functions;
/**
* A type-safe higher-order function that accepts any number of arguments, it returns a function with the parameters of the first function passed and a return type/value of the last function.
*
* @returns a function that takes in the initial type and returns the final type
*/
export function pipe<F extends UnaryFunction[]>(...functions: Validator<F>): (arg: Parameters<F[0]>[0]) => ReturnType<Last<F, any>>;
/**
* Prevent execution of `fn` until `time` has passed
*
* @example
*
* ```js
* function update(name) {...} // can also be inlined
*
* const search = debounce(update, 500);
*
* search('mauss'); // execute after 500ms
* ```
*/
export function debounce<F extends AnyFunction>(fn: F, time?: number): <A extends Parameters<F>>(...args: A) => void;
/**
* Immediately execute `fn` and prevent the next execution until after `time`
*
* @example
*
* ```js
* function update(name) {...}
*
* const onclick = immediate(update, 500);
* ```
*/
export function immediate<F extends AnyFunction>(fn: F, time?: number): <A extends Parameters<F>>(...args: A) => void;
/**
* Prevent executions after the first `fn` until `time` has passed
*
* @example
*
* ```js
* function update(name) {...}
*
* const search = throttle(update, 500);
*
* search('mauss'); // execute every 500ms
* ```
*/
export function throttle<F extends AnyFunction>(fn: F, time?: number): <A extends Parameters<F>>(...args: A) => void;
interface CapitalizeOptions {
/** only capitalize the very first letter */
cap?: boolean;
/** convert the remaining word to lowercase */
normalize?: boolean;
}
/**
* A function that accepts a string and returns the same with the first letter of each word capitalized. This can also be used to capitalize only the first letter of the entire string, or normalize the entire string to lowercase before capitalizing.
*/
export function capitalize(text: string, { cap, normalize }?: CapitalizeOptions): string;
/**
* A function to check for value equality between two variables. This will work for any data type except `function`, which will always return `true` when two function are being compared. The heuristics are as follows:
* - fails immediately when the type of `x` and `y` are not the same
* - type of `function` are not comparable, always returns true
* - type of `symbol` is converted and compared as a `string`
* - primitive values are compared using strict equality operator
* - type of `object`, two empty array or object are considered the same
* - type of `object`, comparing array also considers its length and item order
* - type of `object`, two object must have the same keys before comparing its values
* - type of `object`, the order of key-value pair does not matter for equality check
* - `identical` is infinitely recursive for any amount of nested array/object
*/
export function identical(x: unknown, y: unknown): boolean;
/**
* A function to work with template strings and removes indentation based on the first line. This is useful when the template string is written with indentation for better readability, but the indentation is not desired in the final output.
*/
export function indent(text: string): {
depth: number;
trim(): string;
};
/**
* A function that accepts a function and returns the same function with the order of parameters reversed. This can be used in conjunction with `compare` methods to sort the items in ascending values.
*
* @param fn any function with one or more arguments
* @returns a curried function to take in the arguments
*/
export function inverse<Function extends AnyFunction>(fn: Function): (...parameters: Reverse<Parameters<Function>>) => ReturnType<Function>;
/**
* A drop-in replacement for `new RegExp()` with special characters from source string escaped. This is useful when the pattern is not known at compile time and is dynamically constructed.
*
* @param pattern passed in the form of string literal
* @param flags unique set of characters from `d|g|i|m|s|u|y`
* @returns dynamically constructed RegExp object
*/
export function regexp(pattern: string, flags?: string): RegExp;
/**
* A convenience function to declare a variable with multiple conditionals to determine its final value, without cluttering the global or top-level scope with temporary variables that are only used once, and avoid nested ternary hell.
*/
export function scope<T>(fn: () => T): T;
/**
* A function that accepts an indexable object.
* @returns `{ head, last }` of the object
*/
export function sides<T extends string | any[]>(x: T): Record<'head' | 'last', T[0]>;
/**
* A function that accepts an array and returns the same without any duplicate values. This can also handle an array of object by passing in a `key` as an identifier to access the object, with the same behavior as `key` from `'/compare'` module.
*
* @param array items to be inspected
* @returns duplicate-free version of the array input
*/
export function unique<Inferred extends Record<IndexSignature, any>, Identifier extends Paths<Inferred>>(array: readonly Inferred[], key: string & Identifier): Inferred[];
export function unique<T>(array: readonly T[]): T[];
type Parse<T> = T extends `${string}{${infer P}}${infer R}` ? P | Parse<R> : never;
/**
* A type-safe template string function that accepts a string template with placeholders and returns a function that can take in an object with the same keys as the placeholders. The function will replace the placeholders with the corresponding values from the object. Parameters of the braces can be prefixed with a question mark `?` to make it optional to the type system and will fallback to an empty string if it's not defined in the table.
*
* This assumes the braces inside the template string are balanced and not nested. The function will not throw an error if the braces are not balanced, but the result will be unexpected. If you're using TypeScript and are passing a [string literal](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types), it will point out any unbalanced braces by throwing an error from the compiler.
*
* The template string is parsed into an array of strings, which are then executed with the provided table of functions, which is an object with the key being the name of the braces from the template string, and the value being the function to manipulate the name of the braces.
*
* @example
*
* ```javascript
* import { tsf } from 'mauss/std';
* const render = tsf('https://api.example.com/v1/{category}/{id}');
* function publish({ category, id }) {
* const prefix = // ...
* const url = render({
* category: () => category !== 'new' && category,
* id: (v) => prefix + uuid(`${v}-${id}`),
* });
* return fetch(url);
* }
* ```
*
* @returns a function to replace the placeholders
*/
export function tsf<Input extends string>(template: Input extends `${string}{}${string}` ? 'Empty braces are not allowed in template' : Input extends `${string}{{${string}}}${string}` | `${string}{{${string}}${string}` | `${string}{${string}}}${string}` ? 'Unbalanced braces detected in template' : Input): (table: Record<Exclude<string extends Input ? string : Parse<Input>, `?${string}`>, (string | false | null | undefined) | UnaryFunction<string, string | false | null | undefined>> & { [K in Extract<string extends Input ? string : Parse<Input>, `?${string}`>]?: (string | false | null | undefined) | UnaryFunction<string, string | false | null | undefined>; }) => string;
/** Generic for making any arbitrary function */
type AnyFunction<P extends any[] = any[], R = any> = (...parameters: P) => R;
/** Get the last item from an array, fallback defaults to `never` */
type Last<T extends any[], = never> = T extends [...any[], infer L] ? L : ;
/** Reverses any tuple values */
type Reverse<T extends any[]> = T extends [infer H, ...infer R] ? [...Reverse<R>, H] : [];
/** Any function that has exactly one parameter */
type UnaryFunction<P = any, R = any> = (parameter: P) => R;
type Concat<Left, Right, Delimiter = '.'> = When<[
Left,
Right
], [
string,
string
], `${Left & string}${'' extends Right ? '' : Delimiter & string}${Right & string}`>;
/** Extends a list to a certain specified length */
type Extend<Size extends number, List extends any[] = []> = List['length'] extends Size ? List : Extend<Size, [...List, any]>;
/**
* Generates all possible properties of nested object,
* starting from the root and ends anywhere in the tree.
* @returns string union with dot (.) as the delimiter
*/
type Paths<T> = T extends object ? When<T, Date, '', {
[K in keyof T]-?: `${K & string}` | Concat<K, Paths<T[K]>>;
}[keyof T]> : '';
/** Define a union of tuple that accepts a progressively increasing (LTR) items */
type Progressive<List extends any[]> = List extends [...infer Rest, any] ? List | (Rest['length'] extends 1 ? Rest : Progressive<Rest>) : List;
/** Slices a list beginning from the starting index */
type Slice<List extends any[], Start extends number = 0> = List extends [
...Extend<Start>,
...infer Sliced
] ? Sliced : [];
/** Primitives that are extended by `Record<..., any>` */
type IndexSignature = string | number | symbol;
/** When L extends R, returns `Y`, else `N` */
type When<L, R, Y = true, N = never> = L extends R ? Y : N;
export {};
}
declare module 'mauss/api' {
type HTTPMethods = 'GET' | 'POST' | 'PUT' | 'DELETE';
export interface FetcherConfig {
/**
* Prepares an object to pass into fetch that is called before the request is sent, it receives the specified `method` and `to` url string, and optionally a `body`, `from` URL, and `headers` object. It should _prepare_ and return an object that satisfies the [`RequestInit`](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request) interface
* @param opts request init options
*/
prepare?(opts: {
method: HTTPMethods;
to: string;
body?: BodyInit;
from?: URL;
headers?: Record<string, string>;
}): RequestInit;
/**
* Intercepts the `url` before the request passed to fetch
* @param path url received from all api methods
*/
intercept?(path: string): string;
/**
* Catches error from `fetch` failure and returns a string
*/
sweep?(exception: unknown): string;
/**
* Transforms raw response to desired data structure, it receives the response and can return anything that will used as the `payload`
* @param res response object from fetch
* @default r.json().catch(() => ({}))
*/
transform?(res: Response): Promise<unknown>;
/**
* Determines if fetcher should exit with an error, this function is called after the response is transformed and receives a clone of the initial response and the `payload`
* @param res response object from fetch
* @returns `string` if the request was unsuccessful or anything falsy if it was successful
*/
exit?(res: Response, payload: any): AlsoPromise<string | false | Nullish>;
}
export interface SendOptions {
from?: URL;
headers?: Record<string, string>;
using?: typeof fetch;
}
/**
* Fetcher factory to create a `send` function to make requests that abstracts the `fetch` API.
*
* @example
*
* ```javascript
* import { fetcher, type SendOptions } from 'mauss/api';
* const send = fetcher({
* prepare({ method, to, body }) {
* // ... do some checks or logging
* return {
* method: method || 'GET',
* mode: 'cors',
* credentials: 'include',
* headers: {
* 'Content-Type': 'application/json',
* },
* body: JSON.stringify(body),
* };
* },
* exit({ status }, payload) {
* if (status >= 500) return 'ServerError';
* if (status >= 400) return 'ClientError';
* // void or non-string means successful
* },
* });
* // use the `send` function above to make and export an abstraction
* export const API = {
* // use getter to determine the template and infer the defined parameters
* get 'session/:id'() {
* // `tsf` function from 'mauss/std'
* const render = tsf('https://auth.example/{id}/login');
* return (params: Parameters<typeof render>[0], options: SendOptions = {}) => {
* const target = send(render(params), options);
* return {
* // ... abstraction methods, for example
* async post() {
* return await target.post();
* },
* };
* };
* },
* };
* ```
*/
export function fetcher({ prepare, intercept, sweep, transform, exit, }: FetcherConfig): (url: string, options?: SendOptions) => {
get<T>(): Promise<{
kind: "error";
error: string;
} | {
kind: "success";
value: T;
}>;
post<T>(payload?: any): Promise<{
kind: "error";
error: string;
} | {
kind: "success";
value: T;
}>;
put<T>(payload?: any): Promise<{
kind: "error";
error: string;
} | {
kind: "success";
value: T;
}>;
delete<T>(): Promise<{
kind: "error";
error: string;
} | {
kind: "success";
value: T;
}>;
};
/** Nullish values, which are only `null` and `undefined` */
type Nullish = null | undefined;
/** Expand T to also be a promise */
type AlsoPromise<T> = T | Promise<T>;
export {};
}
declare module 'mauss/bits' {
/**
* Binary search algorithm on a sorted array
* @returns the first item that passes the check
*/
export function binary<T>(sorted: T[], check: {
item: UnaryFunction<T, false | UnaryFunction<T>>;
pointer: UnaryFunction<T, boolean>;
}): T | undefined;
/**
* Find the minimum and maximum values in an array of numbers
*/
export function minmax(array: number[]): [min: number, max: number];
/** Any function that has exactly one parameter */
type UnaryFunction<P = any, R = any> = (parameter: P) => R;
export {};
}
declare module 'mauss/compare' {
/** Compares nullish values, sorting `null` and `undefined` to the end */
export function undefined(x: unknown, y: unknown): number;
/** Compares boolean values, prioritizing `true` over `false` */
export function boolean(x: boolean, y: boolean): number;
/**
* Put `(x, y)` for bigger number first, and `(y, x)` for smaller number first
* @returns `y - x` which defaults to descending order
*/
export function number(x: number, y: number): number;
/** Compares bigint values, defaults to ascending order */
export function bigint(x: bigint, y: bigint): number;
/** Compares symbols using its string values */
export function symbol(x: symbol, y: symbol): number;
/** Compares string values using `.localeCompare` */
export function string(x: string, y: string): number;
type Wildcard =AnyFunction<[x: any, y: any], number>;
/** Compares generic object values using {@link inspect} */
export function object(x: object, y: object): number;
/** Compares anything with anything */
export function wildcard(x: any, y: any): number;
/**
* Recursively compares common object properties until the first difference is found
* @returns `0` if both objects are identical or completely different, otherwise their respective primitive difference
*/
export function inspect(x: Record<IndexSignature, any>, y: Record<IndexSignature, any>): number;
/** Compares date or date-like string values */
export function date(x: string | Date, y: string | Date): number;
/** Compares time or time-like string values */
export function time(x: string | Date, y: string | Date): number;
type KeyValidator<Keys, Expected> = Keys extends [infer I extends string, ...infer R] ? Expected & Record<I, KeyValidator<R, I extends keyof Expected ? Expected[I] : never>> : Expected;
/**
* A higher-order function that accepts a string as an identifier and an optional comparator function, it breaks up the identifier described by the dot (`.`) character and returns a curried function that accepts `(x, y)` with an object defined by the identifier.
*
* The optional comparator can be used when you have an existing custom sort function, e.g. in combination with `compare.order` to sort a set of string.
*
* @example
*
* ```javascript
* import * as compare from 'mauss/compare';
*
* const posts = [
* { date: { month: 'March' } },
* { date: { month: 'June' } },
* { date: { month: 'May' } },
* { date: { month: 'April' } },
* { date: { month: 'January' } },
* { date: { month: 'June' } },
* { date: { month: 'February' } },
* ];
*
* const months = [
* 'January',
* 'February',
* 'March',
* 'April',
* 'May',
* 'June',
* 'July',
* 'August',
* 'September',
* 'October',
* 'November',
* 'December',
* ];
*
* posts.sort(compare.key('date.month', compare.order(months)));
* ```
*/
export function key<Inferred extends Record<IndexSignature, any>, Identifier extends keyof Inferred =Paths<Inferred>>(identifier: string & Identifier, comparator?: Wildcard): <X extends Inferred, Y extends Inferred>(x:WhenAny<keyof X, X, KeyValidator<Split<Identifier, ".">, X>>, y:WhenAny<keyof Y, Y, KeyValidator<Split<Identifier, ".">, Y>>) => number;
/**
* A higher-order function that accepts an array of strings and returns a comparator function that sorts the strings in the order they appear in the array.
*/
export function order(weights: readonly string[]): Wildcard;
/** Primitives that are extended by `Record<..., any>` */
type IndexSignature = string | number | symbol;
/** When L extends R, returns `Y`, else `N` */
type When<L, R, Y = true, N = never> = L extends R ? Y : N;
/** When T is type of `any`, returns `Y`, else `N` */
type WhenAny<T, Y = true, N = false> = When<0, 1 & T, Y, N>;
/** Generic for making any arbitrary function */
type AnyFunction<P extends any[] = any[], R = any> = (...parameters: P) => R;
type Concat<Left, Right, Delimiter = '.'> = When<[
Left,
Right
], [
string,
string
], `${Left & string}${'' extends Right ? '' : Delimiter & string}${Right & string}`>;
/**
* Generates all possible properties of nested object,
* starting from the root and ends anywhere in the tree.
* @returns string union with dot (.) as the delimiter
*/
type Paths<T> = T extends object ? When<T, Date, '', {
[K in keyof T]-?: `${K & string}` | Concat<K, Paths<T[K]>>;
}[keyof T]> : '';
/** Splits a string with custom separator */
type Split<Key extends IndexSignature, Separator extends string> = Key extends `${infer Prefix}${Separator}${infer Rest}` ? [Prefix, ...Split<Rest, Separator>] : [Key];
export {};
}
declare module 'mauss/csv' {
/**
* Parse a CSV content into a 2D array.
*
* @example
* ```javascript
* import { readFileSync } from 'fs';
* import { read } from 'mauss/csv';
* const csv = read(readFileSync('./data.csv', 'utf-8'));
* ```
*
* @returns a 2D array of the CSV content
*/
export function read(content: string): string[][];
export {};
}
declare module 'mauss/date' {
type DateValue = string | number | Date;
/** A function that returns the current date or the date passed in */
export function current(d?: DateValue): Date;
interface BuildOptions {
base?: 'UTC';
}
/**
* A function that builds a formatter
* @see {@link format} for the default formatter
*/
export function build({ base }: BuildOptions): (date?: DateValue) => (mask?: string) => string;
/**
* A function that takes in a `DateValue` and returns a renderer that accepts a string mask to format the date in
* @default 'DDDD, DD MMMM YYYY'
*/
export const format: (date?: DateValue) => (mask?: string) => string;
interface TravelOptions {
/** relative point of reference to travel */
from?: DateValue;
/** relative days to travel in number */
to: number;
}
/**
* Travel `to` a relative date `from` a point of reference
* @returns a new Date object with the relative date
*/
export function travel({ from, to }: TravelOptions): Date;
export {};
}
declare module 'mauss/guards' {
/**
* A guard for exhaustive checks with `if`/`else`/`switch` statements, this will help branching logic in consuming enumeration and union types.
*
* @example
*
* ```typescript
* import { bulwark } from 'mauss/guards';
*
* let key = 'a' as 'a' | 'z';
* switch (key) {
* case 'a':
* return key.charCodeAt();
* default:
* // Argument of type 'string' is not assignable to parameter of type 'never'.
* return bulwark(key);
* }
* ```
*/
export function bulwark(nothing: never): void;
type Empty = '' | Nullish;
/** @returns true if input is not `nullish` or an empty string */
export function exists<T>(i: T | Empty): i is T;
/** @returns true if input is `null` or `undefined` */
export function nullish<T>(i: T | FullPrimitives): i is T;
/** @returns true if input is truthy in general */
export function truthy<T>(i: T | Falsy): i is T;
/** @returns true if input exists or is a number greater than 0 */
export function natural<T>(i: T | Empty): i is T;
/** @returns true if input exists or is a number greater than or equal to 0 */
export function whole<T>(i: T | Empty): i is T;
type ValidNegatives = typeof exists | typeof nullish | typeof truthy;
/** @returns negation of the guard function passed, e.g. `not(nullish)` */
export function not<F extends ValidNegatives>(fn: F): <T>(i: T | (F extends typeof exists ? FullPrimitives : F extends typeof nullish ? Nullish : Empty)) => i is T;
/** @returns true if string input is all lowercase letters */
export function lowercase(s: string): boolean;
/** @returns true if string input is all uppercase letters */
export function uppercase(s: string): boolean;
/** Nullish values, which are only `null` and `undefined` */
type Nullish = null | undefined;
/** Falsy values, value considered false in boolean context */
type Falsy = false | 0 | '' | Nullish;
/** Basic primitives consisting of `string`, `number`, and `boolean` */
type Primitives = string | number | boolean;
/** Primitives from `typeof` as their actual type */
type FullPrimitives = Primitives | bigint | symbol;
export {};
}
declare module 'mauss/math' {
/**
* Calculates the mean from a list of numbers using an incremental approach (moving average algorithm), which uses a constant space and updates in constant time. This method helps avoid potential numerical instability issues when dealing with a large sum, such as an integer overflow.
*
* @example
* ```javascript
* // returns 3
* average([1, 2, 3, 4, 5]);
* ```
*/
export function average(numbers: number[]): number;
/** A higher-order function that returns a function to clamp a number between a minimum and maximum value */
export function clamp(min: number, max: number): (value: number) => number;
/**
* The `%` is a remainder operator, this function computes the modulo operation and ensures a non-negative number for a non-negative divisor.
*
* @example
* ```javascript
* // returns 1
* modulo(5, 2);
*
* // returns 1
* modulo(-3, 2);
* ```
*/
export function modulo(a: number, n: number): number;
/** generate all possible permutations from all items in an array */
export function permutation<T, K>(input: T[], fn?: (i: T[]) => K): (K | T[])[];
export {};
}
declare module 'mauss/promises' {
export function debounce<F extends AnyFunction>(fn: F, time?: number): <A extends Parameters<F>>(...args: A) => Promise<ReturnType<F>>;
export function pause(ms: number): Promise<string>;
/** Generic for making any arbitrary function */
type AnyFunction<P extends any[] = any[], R = any> = (...parameters: P) => R;
export {};
}
declare module 'mauss/random' {
/**
* Generates a random floating point number between `min` and `max`
* @default max=1
* @default min=0
*/
export function float(max?: number, min?: number): number;
/**
* Generates a random integer between `min` and `max`
* @default max=1
* @default min=0
*/
export function int(max?: number, min?: number): number;
/** Generates a random boolean value */
export function bool(): boolean;
/** Generates an array of random integers */
export function array(length: number, max: number, min?: number): number[];
/** Gets a random property from an object */
export function key(dict: Record<IndexSignature, any>): string;
/** Gets a value of a random property from an object */
export function val<T>(dict: Record<IndexSignature, T>): T;
/** Gets a random item from a list */
export function item<T>(list: T[]): T;
/** Generates a random hexadecimal color code */
export function hex(): string;
/** Generates a random IPv4 address */
export function ipv4(): string;
interface WebCryptoMethods {
getRandomValues(array: TypedIntArray): TypedIntArray;
randomUUID(): string;
}
/** Generates a random UUID */
export function uuid<Generator extends WebCryptoMethods>(gen?: Generator): string;
/** Primitives that are extended by `Record<..., any>` */
type IndexSignature = string | number | symbol;
/** Integer-based instances of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects */
type TypedIntArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | BigUint64Array | BigInt64Array;
export {};
}
declare module 'mauss/std' {
/** Augments the source object with various utility methods */
export function augment<O extends object>(object: O): {
/** @returns a new object with all the keys passed */
build<Keys extends readonly string[]>(keys: Narrow<Keys>): { [K in Keys[number]]: K extends keyof O ? O[K] : null; };
/** @returns an array of strongly-typed object entries */
readonly entries: Entries<O>;
/** @returns a new object with only the keys passed */
filter<Keys extends readonly string[]>(keys: Narrow<Keys>): Pick<O, Keys[number]>;
/** Deep freezes the current object */
freeze(): Freeze<O>;
/** @returns an array of strongly-typed object keys */
readonly keys: Array<string & keyof O>;
/** @returns the total number of properties in the object */
readonly size: number;
};
/**
* Creating a copy of a data type, especially an object, is useful for removing the reference to the original object, keeping it clean from unexpected changes and side effects. This is possible because we are creating a new instance, making sure that any mutation or changes that are applied won't affect one or the other
* @returns a deep copy of the object input
*/
export function clone<T>(i: T): T;
/**
* Iterate over the key-value pair of an object, returns a new object using the pairs returned from the callback function. If callback is omitted, the default behavior will create a deep copy of the original object
*
* The returned object will be filtered to only contain a key-value pair of the 2-tuple from `fn()`, any other values returned from the callback will be ignored, i.e. `void | Falsy`
*/
export function iterate<T extends object, I = T[keyof T]>(object: T, callback?: AnyFunction<[
entry: Entries<T>[number],
index: number
], void | Falsy | [IndexSignature, I]>): I extends T[keyof T] ? T : unknown;
/** Aggregates elements from each of the arrays and returns a single array of objects with the length of the largest array */
export function zip<T extends Array<Nullish | {}>>(...arrays: T[]): Record<IndexSignature, any>[];
type Narrowable = void | symbol | Nullish | Primitives | object | {};
/** Nullish values, which are only `null` and `undefined` */
type Nullish = null | undefined;
/** Falsy values, value considered false in boolean context */
type Falsy = false | 0 | '' | Nullish;
/** Basic primitives consisting of `string`, `number`, and `boolean` */
type Primitives = string | number | boolean;
/** Primitives that are extended by `Record<..., any>` */
type IndexSignature = string | number | symbol;
/** Generic for making any arbitrary function */
type AnyFunction<P extends any[] = any[], R = any> = (...parameters: P) => R;
/** Strongly-type array of tuple from object in `Object.entries` */
type Entries<T> = {
[K in keyof T]-?: [string & NonNullable<keyof PickByValue<T, T[K]>>, T[K]];
}[keyof T][];
type Fallback<A, B> = A extends B ? A : B;
/** Recursively make all properties of object T as readonly */
type Freeze<T> = {
readonly [P in keyof T]: T[P] extends Function ? T[P] : Freeze<T[P]>;
};
/** Pick the properties of T that satisfies type of V */
type PickByValue<T, V> = Pick<T, {
[K in keyof T]: T[K] extends V ? K : never;
}[keyof T]>;
type Narrow<T> = Fallback<T, [
] | (T extends Narrowable ? T : never) | {
[K in keyof T]: Narrow<T[K]>;
}>;
export {};
}
declare module 'mauss/sys' {
/** Joins all given parameters together using `/`, regardless of the platform */
export function catenate(...paths: string[]): string;
export {};
}
declare module 'mauss/web' {
/** Possible cookie inputs, `null | undefined` from headers */
type CookieInput = string | null | undefined;
interface CookieOptions {
/**
* Expiry in days
* @default 6
*/
expires?: number;
/**
* MaxAge in days
* @default undefined */
maxAge?: number;
/**
* Domain
* @default undefined
*/
domain?: string;
/**
* Path
* @default '/'
*/
path?: string;
/**
* HttpOnly
* @default false
*/
secure?: boolean;
/**
* HttpOnly
* @default true
*/
httpOnly?: boolean;
/**
* SameSite
* @default 'Strict'
*/
sameSite?: 'Strict' | 'Lax' | 'None';
}
export const cookies: {
parse(source?: CookieInput): {
has: (key: string) => boolean;
get: (key: string) => string | undefined;
keys: () => string[];
values: () => (string | undefined)[];
entries: () => [string, string | undefined][];
};
/**
* Locates a cookie and immediately returns the raw value
* @param source cookie source to parse
* @param name cookie name to search for
* @param trim remove quotes in cookie value, if there is any
* @returns the value of cookie name and empty string if it doesn't exist
*/
raw(source: CookieInput, name: string, trim?: boolean): string | undefined;
/**
* @param options cookie settings
* @returns a set-cookie function
*/
create({ path, domain, maxAge, expires, sameSite, secure, httpOnly, }?: CookieOptions): (name: string, value: string) => string;
/**
* A convenience function for the default `create()`
*
* @param name name for cookie
* @param value value to be saved as cookie name
* @returns the complete 'Set-Cookie' value
*/
readonly set: (name: string, value: string) => string;
/**
* @param values object of string pair as name and value for cookies
* @param options cookie settings
* @returns array of the complete 'Set-Cookie' values
*/
bulk(values: Record<string, string>, options?: CookieOptions): string[];
/**
* Automatically remove cookie in browser
* @param name cookie to expire
* @returns expiring 'Set-Cookie' value
*/
remove(name: string): string;
};
function copy(data: string | ClipboardItem, handler?: {
accept?(): AlsoPromise<void>;
reject?(): AlsoPromise<void>;
}): Promise<void>;
function paste(type: 'blob'): Promise<ClipboardItems>;
function paste(type: 'text'): Promise<string>;
/**
* This namespace extends the [`Navigator` object](https://developer.mozilla.org/en-US/docs/Web/API/Navigator), make sure to execute the function in environments where `window.navigator` exists
*/
export const clipboard: {
copy: typeof copy;
paste: typeof paste;
item(type: string, data: string | Blob, options?: ClipboardItemOptions): ClipboardItem;
};
type CombineExisting<A extends Record<IndexSignature, any>, B extends Record<IndexSignature, any>, Duplicate = Intersection_1<A, B>> = Omit<A, keyof Duplicate> & Omit<B, keyof Duplicate> & {
[P in keyof Duplicate]: Flatten<[A[P], B[P]]>;
};
type QueryDecoder<Query extends string> = string extends Query ? Record<IndexSignature, string | readonly string[]> : Query extends `${infer Leading}${infer Rest}` ? Leading extends '?' ? QueryDecoder<Rest> : `${Leading}${Rest}` extends `${infer Param}&${infer Next}` ? CombineExisting<QueryDecoder<Param>, QueryDecoder<Next>> : `${Leading}${Rest}` extends `${infer Key}=${infer Value}` ? {
[K in Key]: Value;
} : {} : {};
/**
* Query string decoder (`qsd`) decodes a query string into an object. It accepts a query string with or without the leading `?` and returns a mapped object of decoded query string
*
* @param qs query string of a URL with or without the leading `?`
* @returns mapped object of decoded query string
*/
export function qsd<Q extends string>(qs: Q): QueryDecoder<Q>;
type BoundValues = Nullish | Primitives;
/**
* Query string encoder (`qse`) encodes key-value pairs from an object into a query string. It optionally accepts a second argument for a transformer function that will be applied to the final value if it exists, else an empty string will be returned
*
* @param bound object with key-value pair to be updated in the URL, only accepts an object with nullish and primitive literals or an array of those values
* @param transformer function that is applied to the final string if it exists, useful in cases where we want to add a leading `?` when the query exists but not when it's empty, or when we would like to append another existing query string after only if the output of `qse` exists
* @returns final query string
*/
export function qse<T extends object>(bound: T[keyof T] extends BoundValues | readonly BoundValues[] ? T : never, transformer?: (final: string) => string): string;
/** Expand T to also be a promise */
type AlsoPromise<T> = T | Promise<T>;
/** Nullish values, which are only `null` and `undefined` */
type Nullish = null | undefined;
/** Basic primitives consisting of `string`, `number`, and `boolean` */
type Primitives = string | number | boolean;
/** Primitives that are extended by `Record<..., any>` */
type IndexSignature = string | number | symbol;
/** Pick the properties of A that also exists in B */
type Intersection_1<A, B> = Pick<A, Extract<keyof A, keyof B> & Extract<keyof B, keyof A>>;
/** Flattens any array recursively */
type Flatten<List extends any[], Memory extends any[] = []> = List extends [] ? Memory : List extends [infer Head, ...infer Rest] ? Head extends any[] ? Flatten<[...Head, ...Rest], Memory> : Flatten<Rest, [...Memory, Head]> : never;
export {};
}
declare module 'mauss/typings' {
export type Narrowable = void | symbol | Nullish | Primitives | object | {};
/** Nullish values, which are only `null` and `undefined` */
export type Nullish = null | undefined;
/** Falsy values, value considered false in boolean context */
export type Falsy = false | 0 | '' | Nullish;
/** Basic primitives consisting of `string`, `number`, and `boolean` */
export type Primitives = string | number | boolean;
/** Primitives from `typeof` as their actual type */
export type FullPrimitives = Primitives | bigint | symbol;
/** Primitive values from `typeof` as string union */
export type TypePrimitive = 'string' | 'number' | 'bigint' | 'boolean' | 'symbol';
/** The complete values from `typeof` as string union */
export type TypeTable = TypePrimitive | 'undefined' | 'object' | 'function';
/** Primitives that are extended by `Record<..., any>` */
export type IndexSignature = string | number | symbol;
/** Integer-based instances of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects */
export type TypedIntArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | BigUint64Array | BigInt64Array;
/** Complete instances of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects */
export type TypedArray = TypedIntArray | Float32Array | Float64Array;
/** When L extends R, returns `Y`, else `N` */
export type When<L, R, Y = true, N = never> = L extends R ? Y : N;
/** When T is type of `any`, returns `Y`, else `N` */
export type WhenAny<T, Y = true, N = false> = When<0, 1 & T, Y, N>;
/** When T is type of `Function`, returns `Y`, else `N` */
export type WhenFunction<T, Y = true, N = false> = When<T, Function, Y, N>;
/** When T is type of `never`, returns `Y`, else `N` */
export type WhenNever<T, Y = true, N = false> = When<[T], [never], Y, N>;
/** When T is type of `object`, returns `Y`, else `N` */
export type WhenObject<T, Y = true, N = false> = When<T, object, Y, N>;
/** When T is type of `unknown`, returns `Y`, else `N` */
export type WhenUnknown<T, Y = true, N = false> = When<unknown, T, Y, N>;
/** Expand T to also be an array */
export type AlsoArray<T> = T | T[];
/** Expand T to also be a promise */
export type AlsoPromise<T> = T | Promise<T>;
/** Expand T to an array and the readonly version */
export type ArrayConstant<T> = T[] | readonly T[];
/** Generic for making any arbitrary function */
export type AnyFunction<P extends any[] = any[], R = any> = (...parameters: P) => R;
/** Exclude `undefined` from T */
export type Definable<T> = T extends undefined ? never : T;
/** Exclude all union that is in both A and B and get the difference */
export type Difference<A, B> = Exclude<A | B, A & B>;
/** Allow either A or B but not both at the same time */
export type Either<A, B> = Only<A, B> | Only<B, A>;
/** Strongly-type array of tuple from object in `Object.entries` */
export type Entries<T> = {
[K in keyof T]-?: [string & NonNullable<keyof PickByValue<T, T[K]>>, T[K]];
}[keyof T][];
export type Fallback<A, B> = A extends B ? A : B;
/** Remove type from T that does not satisfy type of Validator */
export type Filter<T, Validator> = T extends Validator ? T : never;
/** Get the first item from an array, fallback defaults to `never` */
export type First<T extends any[], Fallback = never> = T extends [infer F, ...any[]] ? F : Fallback;
/** Allow autocompletion of union in addition to arbitrary values */
export type Flexible<Union extends T, T = string> = Union | (T & Record<never, never>);
/** Recursively make all properties of object T as readonly */
export type Freeze<T> = {
readonly [P in keyof T]: T[P] extends Function ? T[P] : Freeze<T[P]>;
};
/** Pick the properties of A that also exists in B */
type Intersection_1<A, B> = Pick<A, Extract<keyof A, keyof B> & Extract<keyof B, keyof A>>;
/** Infers the return value of toJSON on the properties */
export type JSONState<T> = {
[P in keyof T]: T[P] extends {
toJSON: () => infer J;
} ? J : T[P];
};
/** Get the last item from an array, fallback defaults to `never` */
export type Last<T extends any[], Fallback = never> = T extends [...any[], infer L] ? L : Fallback;
/** Defines a type with at least one item */
export type NonEmptyArray<T> = [T, ...T[]];
/** Disallow any properties from B when defining A */
export type Only<A, B> = {
[P in keyof A]: A[P];
} & Omit<{
[P in keyof B]?: never;
}, keyof A>;
/** Overwrite properties in A with values from B */
export type Overwrite<A, B> = Omit<A, keyof B> & B;
/** Pick the properties of T that satisfies type of V */
export type PickByValue<T, V> = Pick<T, {
[K in keyof T]: T[K] extends V ? K : never;
}[keyof T]>;
/** Reverses any tuple values */
export type Reverse<T extends any[]> = T extends [infer H, ...infer R] ? [...Reverse<R>, H] : [];
/** Strict properties narrowing and remove Index Signatures */
export type Strict<T> = {
[P in keyof T as {} extends Record<P, any> ? never : P]: T[P];
};
/** Workaround for a type not fulfilling index signature constraint */
export type Typify<T> = {
[P in keyof T]: Typify<T[P]>;
};
/** Any function that has exactly one parameter */
export type UnaryFunction<P = any, R = any> = (parameter: P) => R;
export type Concat<Left, Right, Delimiter = '.'> = When<[
Left,
Right
], [
string,
string
], `${Left & string}${'' extends Right ? '' : Delimiter & string}${Right & string}`>;
/** Extends a list to a certain specified length */
export type Extend<Size extends number, List extends any[] = []> = List['length'] extends Size ? List : Extend<Size, [...List, any]>;
/** Flattens any array recursively */
export type Flatten<List extends any[], Memory extends any[] = []> = List extends [] ? Memory : List extends [infer Head, ...infer Rest] ? Head extends any[] ? Flatten<[...Head, ...Rest], Memory> : Flatten<Rest, [...Memory, Head]> : never;
/** Convert Union to Intersection */
export type IntersectUnion<U> = (U extends any ? (_: U) => void : never) extends (_: infer Intersection) => void ? Intersection : never;
/** Joins a list of string with custom delimiter */
export type Join<StringList extends readonly string[], Delimiter extends string = '-'> = StringList extends readonly [infer Head, infer Next, ...infer Rest] ? Join<[
`${Head & string}${Delimiter}${Next & string}`,
...Extract<Rest, readonly string[]>
], Delimiter> : StringList extends readonly [infer OnlyItem] ? OnlyItem : '';
export type Narrow<T> = Fallback<T, [
] | (T extends Narrowable ? T : never) | {
[K in keyof T]: Narrow<T[K]>;
}>;
/**
* Merge an object properties and make all of them optional.
* But, when one of it is defined, all of it's other properties
* needs to be defined as well.
*/
export type OptionalAnnex<T, Annex> = T extends {
[P in keyof Annex]: {
[K in P]: Annex[K];
};
}[keyof Annex] ? Annex & T : T;
/**
* Partially omits object properties, like {@link Omit} but
* makes them optional instead
*/
export type PartialOmit<T, Keys extends keyof T, Saved = {
[P in Exclude<keyof T, Keys>]: T[P];
}, Final = Saved & {
[P in keyof T]?: T[P];
}> = {
[P in keyof Final]: Final[P];
};
/**
* Generates all possible properties of nested object,
* starting from the root and ends anywhere in the tree.
* @returns string union with dot (.) as the delimiter
*/
export type Paths<T> = T extends object ? When<T, Date, '', {
[K in keyof T]-?: `${K & string}` | Concat<K, Paths<T[K]>>;
}[keyof T]> : '';
/** Generates a list of tuples from union */
export type Permutation<Union, Sliced = Union> = [Union] extends [never] ? [] : Union extends Union ? [Union, ...Permutation<Sliced extends Union ? never : Sliced>] : never;
/** Define a union of tuple that accepts a progressively increasing (LTR) items */
export type Progressive<List extends any[]> = List extends [...infer Rest, any] ? List | (Rest['length'] extends 1 ? Rest : Progressive<Rest>) : List;
/**
* Single out a property from an object, receives object of
* any properties and only allow one property to be defined
*/
export type SingleProperty<T> = {
[P in keyof T]: {
[K in P]: T[P];
} & {
[K in Exclude<keyof T, P>]?: undefined;
};
}[keyof T];
/** Slices a list beginning from the starting index */
export type Slice<List extends any[], Start extends number = 0> = List extends [
...Extend<Start>,
...infer Sliced
] ? Sliced : [];
/** Splits a string with custom separator */
export type Split<Key extends IndexSignature, Separator extends string> = Key extends `${infer Prefix}${Separator}${infer Rest}` ? [Prefix, ...Split<Rest, Separator>] : [Key];
/**
* Specify tuple of `Size` with items of `T`
*/
export type Tuple<Size extends number, T extends any[] = [], Virtual extends any[] = []> = Virtual['length'] extends Size ? Virtual : Tuple<Size, T, [T, ...Virtual]>;
export { Intersection_1 as Intersection };
}
//# sourceMappingURL=index.d.ts.map