Opinionated collection of utilities and helpers, assembled with Deno in mind.
import * as _ from "https://deno.land/x/[email protected]/mod.ts";
├── deps.ts
├── mod.ts
├── src/
| ├── cache.ts
| ├── collection.ts
| ├── date.ts
| ├── fmt.ts
| ├── hash.ts
| ├── http.ts
| ├── json.ts
| ├── log.ts
| ├── math.ts
| ├── memoize.ts
| ├── params.ts
| ├── promises.ts
| ├── serialize_map.ts
| ├── serialize_set.ts
| ├── state.ts
| ├── throttle.ts
| └── type.ts
├── tests/
| ├── date_test.ts
| ├── memoize_test.ts
| ├── params_test.ts
| ├── promises_test.ts
| ├── serialize_map_test.ts
| ├── serialize_set_test.ts
| └── throttle_test.ts
└── types.d.ts
See the Deno Documentation for this file.
const globalCache: Cache;
function createCache(capacity: number, cacheKey: string): Cache;
See the Deno Documentation for this file.
type SortKeyFn<T> = (keyof T) | ((el: T) => T[keyof T]);
type SortCompareFn<T> = (...args: [T, T]) => number;
function toArray(array?: Nullable<Arrayable<T>>): Array<T>;
function flattenArrayable(array?: Nullable<Arrayable<T | Array<T>>>): T[];
function mergeArrayable(...args: Nullable<Arrayable<T>>[]): Array<T>;
function partition(array: readonly T[], ...filters: PartitionFilter<T>[]);
function uniq(array: readonly T[]): T[];
function last(array: readonly T[]): T;
function at(array: readonly T[], index: number): T;
function remove(array: T[], value: T): T[];
function range(start: number, stop: number, step?: number): number[];
function move(arr: T[], from: number, to: number): T[];
function clampArrayRange(n: number, arr: readonly unknown[]);
function shuffle(array: T[]): T[];
function hasOwnProperty(obj: T, v: PropertyKey): boolean;
function assign<T extends {}, U, V extends any[] = U[]>(
target: T,
...sources: V[]
): asserts target is T & V[any];
function isKeyOf<T extends object>(obj: T, k: keyof any): k is keyof T;
function objectKeys<T extends object>(obj: T): (keyof T)[];
function objectValues<T extends any>(obj: Record<string, T>): T[];
function objectEntries<T extends object>(obj: T): [string, any][];
function pick<
T extends any,
K extends (keyof T & string),
>(o: T, keys: K[]): Record<K, T[K]>;
function filterKeys(
record: Readonly<Record<string, T>>,
predicate: (key: string) => boolean,
): Record<string, T>;
function filterValues(
record: Readonly<Record<string, T>>,
predicate: (value: T) => boolean,
): Record<string, T>;
function filterEntries(
record: Readonly<Record<string, T>>,
predicate: (entry: [string, T]) => boolean,
): Record<string, T>;
function removeEmptyValues<T extends object>(obj: T): T;
function mapKeys(
record: Readonly<Record<string, T>>,
transformer: (key: string) => string,
): Record<string, T>;
function mapValues(
record: Readonly<Record<string, T>>,
transformer: (value: T) => O,
): Record<string, O>;
function mapEntries<
TK extends string,
TV extends any,
OK extends string = TK,
OV extends any = TV,
>(
record: Record<TK, TV>,
mapFn: (entry: [keyof TK, TV]) => [keyof OK, OV],
): Record<OK, OV>;
function objectMap<V, NV extends V, K extends string>(
obj: Record<K, V>,
fn:
| ((value: V, key?: K) => Maybe<[K, V]>)
| (([key, value]: [K, V]) => Maybe<[K, V]>),
): Record<K, V>;
function sortBy<T extends Record<string, any>>(
array: T[],
key: SortKeyFn<T>,
): T[];
function sortInPlace<T extends Record<string, any>>(
array: T[],
key: SortKeyFn<T>,
): T[];
function sortFactory<T extends Record<string, any>>(
key: SortKeyFn<T>,
): SortCompareFn<T> {
return function (a, b) {
const fn: SortKeyFn<T> = (el) => (
typeof key === "function" ? key(el) : el[key]
);
return (fn.call(fn, a)).localeCompare(fn.call(fn, b));
};
}
See the Deno Documentation for this file.
interface RelativeTimeOptions extends Intl.RelativeTimeFormatOptions {
locales?: string | string[];
absolute?: boolean;
timeZone?: string;
}
enum Times {
/**
* set to 1 to scale everything down to seconds.
* leave as 1e3 to scale everything as milliseconds.
*/
second = 1e3,
millisecond = 1e-3 * second,
microsecond = 1e-6 * second,
nanosecond = 1e-9 * second,
minute = 60 * second,
hour = 3.6e3 * second,
day = 8.64e4 * second,
week = 6.048e5 * second,
month = 2.628e6 * second,
year = 3.1536e7 * second,
}
enum TimesAbbr {
millis = Times.millisecond,
nanos = Times.nanosecond,
micros = Times.microsecond,
sec = Times.second,
min = Times.minute,
hr = Times.hour,
wk = Times.week,
mo = Times.month,
yr = Times.year,
ms = Times.millisecond,
ns = Times.nanosecond,
us = Times.microsecond,
s = Times.second,
m = Times.minute,
h = Times.hour,
d = Times.day,
w = Times.week,
M = Times.month,
Y = Times.year,
}
const CENTURY = Times.year * 100;
const DECADE = Times.year * 10;
const YEAR = Times.year;
const QUARTER = Times.year / 4;
const MONTH = Times.month;
const WEEK = Times.week;
const DAY = Times.day;
const HOUR = Times.hour;
const MINUTE = Times.minute;
const SECOND = Times.second;
const MILLISECOND = Times.millisecond;
const NANOSECOND = Times.nanosecond;
const MICROSECOND = Times.microsecond;
function parse(
date: string | number,
formatString = defaultFormatString,
): Date;
function format(
date: Date | string | number,
formatString = defaultFormatString,
): string;
function difference(
from: number | string | Date,
to: number | string | Date,
options?: DifferenceOptions,
): Partial<DifferenceFormat>;
function relative(
value: number,
unit: RelativeUnit,
{
style = "long",
numeric = "auto",
locales = "en",
localeMatcher = "best fit",
}: RelativeTimeOptions = {},
): string;
See the Deno Documentation for this file.
See the Deno Documentation for this file.
const utf8TextEncoder: TextEncoder;
const utf8TextDecoder: TextDecoder;
function toHex(buffer: Uint8Array | ArrayBuffer): string;
async function computeHash(
data: string | Uint8Array,
algorithm: AlgorithmIdentifier = "SHA-1",
): Promise<string>;
async function sha1(data: string | Uint8Array): Promise<string>;
async function sha256(data: string | Uint8Array): Promise<string>;
async function sha512(data: string | Uint8Array): Promise<string>;
async function eTag(data: any, weak = true): Promise<string>;
function uuid(): string;
See the Deno Documentation for this file.
/** Information about the connection a request arrived on. */
interface ConnInfo {
/** The local address of the connection. */
readonly localAddr: Deno.Addr;
/** The remote address of the connection. */
readonly remoteAddr: Deno.Addr;
}
declare type Handler = (
request: Request,
connInfo: ConnInfo,
params: PathParams,
) => Promise<Response> | Response;
interface Routes {
[path: string]: Handler;
}
interface ServeInit extends Partial<Deno.ListenOptions> {
/** An AbortSignal to close the server and all connections. */
signal?: AbortSignal;
/** The handler to invoke when route handlers throw an error. */
onError?: (error: unknown) => Response | Promise<Response>;
/** The callback which is called when the server started listening */
onListen?: (params: { hostname: string; port: number }) => void;
}
declare type PathParams = Record<string, string> | undefined;
export interface ServeStaticOptions {
/** The base to be used for the construction of absolute URL. */
baseUrl: string;
/** A function to modify the response before it's served to the request.
* For example, set appropriate content-type header.
*
* @default undefined */
intervene?: (
request: Request,
response: Response,
) => Promise<Response> | Response;
/** Disable caching of the responses.
*
* @default true */
cache?: boolean;
}
interface RequestTerms {
[key: string]: {
headers?: string[];
body?: string[];
params?: string[];
};
}
export declare type ResponseProps = Record<string, any>;
/**
* Given an extension, lookup the appropriate media type for that extension.
* Likely you should be using `contentType()` though instead.
*/
function lookupMediaType(pathname: string): string | undefined;
/** serve() registers "fetch" event listener and invokes the provided route
* handler for the route with the request as first argument and processed path
* params as the second.
*
* @example
* ```ts
* serve({
* "/": (request: Request) => new Response("Hello World!"),
* 404: (request: Request) => new Response("not found")
* })
* ```
*
* The route handler declared for `404` will be used to serve all
* requests that do not have a route handler declared.
* @see {@link https://deno.land/x/[email protected]/mod.ts}
*/
function serve(userRoutes: Routes, options?: ServeInit): void;
function handleRequest(
request: Request,
connInfo: ConnInfo,
routes: Routes,
): Promise<Response>;
function defaultNotFoundPage(): Response;
/**
* Serve static files hosted on the internet or relative to your source code.
*
* Be default, up to 20 static assets that are less than 10MB are cached. You
* can disable caching by setting `cache: false` in the options object.
*
* @example ```ts
* import { serve, serveStatic } from "https://deno.land/x/[email protected]/src/http.ts"
*
* serve({
* // It is required that the path ends with `:filename+`
* "/:filename+": serveStatic("public", { baseUrl: import.meta.url }),
* })
* ```
*/
function serveStatic(
relativePath: string,
{ baseUrl, intervene, cache }: ServeStaticOptions,
): Handler;
/**
* Renders JSX components to HTML and returns a Response with `text/html`
* as the `content-type.`
*
* @example
* ```jsx
* import { serve, jsx, h } from "https://deno.land/x/sift/mod.ts"
*
* const Greet = ({name}) => <div>Hello, {name}</div>;
*
* serve({
* "/": () => jsx(<html><Greet name="Sift" /></html),
* })
* ```
*
* Make sure your file extension is either `.tsx` or `.jsx` and you've `h` imported
* when using this function. */
function jsx(jsx: VNode, init?: ResponseInit): Response;
/**
* Validate whether the incoming request meets the provided terms.
*/
function validateRequest(
request: Request,
terms: RequestTerms,
): Promise<{
error?: {
message: string;
status: number;
};
body?: {
[key: string]: unknown;
};
}>;
function toResponse(
data: string | ArrayBuffer,
{ contentType, status, headers, ...init }?: ResponseInit & ResponseProps,
): Promise<Response>;
See the Deno Documentation for this file.
declare type JsonReplacerFn = (
this: any,
key: string,
value: any,
) => any;
declare type JsonValue<T extends any = string | number | boolean> = T extends (
T | T[] | Record<string, (T | T[] | Record<string, T>)>
) ? T
: never;
declare type JsonInit = {
replacer?: Maybe<OmitThisParameter<JsonReplacerFn>>;
space?: string | number;
} & ResponseInit;
declare type JsonInitAlt = {
replacer: (string | number)[];
space: string | number;
} & ResponseInit;
/**
* Serializes the given JavaScript value to a JSON string, returning it as a
* new Response with appropriate `content-type` and CORS headers applied.
* Accepts the same init parameters as `JSON.stringify()` and ResponseInit.
*/
function json<T extends unknown>(
data: T, init?: Partial<JsonInit>
): Response (+1 overload)
See the Deno Documentation for this file.
type LogLevelName = "debug" | "info" | "warn" | "error" | "fatal";
enum LogLevel {
Debug,
Info,
Warn,
Error,
Fatal,
}
class Timing {
#t = performance.now();
reset() {
this.#t = performance.now();
}
stop(message: string) {
const now = performance.now();
const d = Math.round(now - this.#t);
let cf = ansi.green;
if (d > 10000) {
cf = ansi.red;
} else if (d > 1000) {
cf = ansi.yellow;
}
console.debug(ansi.dim("TIMING"), message, "in", cf(d + "ms"));
this.#t = now;
}
}
class Logger {
get level(): LogLevel;
set level(level: LogLevel | LogLevelName);
setLevel(level: LogLevelName): void;
debug(...args: unknown[]): void;
log(...args: unknown[]): void;
info(...args: unknown[]): void;
warn(...args: unknown[]): void;
error(...args: unknown[]): void;
fatal(...args: unknown[]): void;
timing(): {
reset(): void;
stop(message?: string): void;
} | Timing;
}
const log: Logger;
See the Deno Documentation for this file.
function clamp(n: number, min: number, max: number): number;
function randomInteger(lower: number, upper: number): number;
function sum(...values: number[] | number[][]): number;
See the Deno Documentation for this file.
interface MemoizeOptions<A extends unknown[], R> {
/**
* Provides a single value to use as the Key for the memoization.
* Defaults to `JSON.stringify` (ish).
*/
hash?: (...args: A) => unknown;
/**
* The Cache implementation to provide. Must be a Map or Map-alike.
* Defaults to a Map. Useful for replacing the cache with an LRU cache or similar.
*/
cache?: Map<unknown, R>;
}
dsss;
type MemoizableFn<
A extends unknown[],
R extends any,
T extends unknown,
> = (this: T, ...args: A) => R;
const defaultOptions: {
cache: Map<any, any>;
hash(...args: any[]): string;
};
function memoize<
A extends unknown[],
R extends unknown,
T extends unknown,
>(
fn: MemoizableFn<A, R, T>,
opts: MemoizeOptions<A, R> = defaultOptions,
): MemoizableFn<A, R, T>;
function memoized<A extends unknown[], R, T>(
options: MemoizeOptions<A, R> = {},
): MemoizeDecoratorFactory<A, R, T>;
See the Deno Documentation for this file.
type Obj<T extends string = string> = Record<string, T>;
type ParamsInit =
| string
| string[][]
| Record<string, string>
| URLSearchParams;
interface ParamsOptions {
distinct?: boolean;
sort?: boolean;
defaultParams?: Record<string, string>;
}
class Params extends URLSearchParams {
readonly options: ParamsOptions;
constructor(init?: ParamsInit, options?: ParamsOptions);
/**
* Sorts all parameters, flattens any keys with multiple values (using
* the last value encountered as each key's final value), and then sorts
* them once again.
* @category Params
* @returns reference to the original Params object with any duplicates removed
* @example ```ts
* import { Params } from "./params.ts";
*
* const params = new Params("key=val1&key2=val2&key=val3");
* params.distinct().toString();
* // key=val3&key2=val2
* ```
*/
distinct(): Params;
get size(): number;
get length(): number;
get<T extends any = string>(name: string | string[]): T | T[];
getAll(names: string | string[]): any;
/**
* Parse parameters from a string, array of entries, object literal, or
* an existing Params / URLSearchParams instance. Allows parameters with
* semicolon (`;`) delimiters, per the IETF RFC specification.
* @param value raw value to be parsed
* @returns
*/
parse<T extends ParamsInit>(value: T): Params (+3 overloads)
toJSON(): {
[k: string]: string;
};
toString(): string;
toObject(): Obj;
static toObject<T extends any = {
[K: string]: string;
}>(params: Params): T;
/**
* Verify if an arbitrary value is fit for initializing a Params instance.
* @param value
* @returns
*/
static validate(value: unknown, named?: boolean): value is ParamsInit;
}
See the Deno Documentation for this file.
function sleep(ms: number, callback?: Fn<void>): Promise<void>;
function throttle(
callback: Fn<void, any> | ((...args: any[]) => any),
delay?: number,
debounceMode?: boolean,
noTrailing?: boolean,
): {
(this: any, ...args: any[]): void;
cancel: () => void;
};
function debounce(
callback: Fn<any>,
delay: number,
atBegin?: boolean,
): {
(this: any, ...args: any[]): void;
cancel: () => void;
};
See the Deno Documentation for this file.
See the Deno Documentation for this file.
See the Deno Documentation for this file.
See the Deno Documentation for this file.
MIT © 2022 Nicholas Berlette • MIT © 2018-2022 the Deno Authors • MIT © 2019-2022 Anthony Fu
All rights reserved.
Apologies to any contributors not included here - email me to have these credits amended with your license/copyright info. Thank you!