1.0.1 • Published 5 months ago
@bethel-nz/abstraction v1.0.1
Abstraction
A framework-agnostic TypeScript/JavaScript utility library for declarative, function-driven abstractions. It provides a fluent, English-like API to simplify complex tasks like scheduling, data manipulation, event handling, and conditional logic.
Installation
npm install @bethel-nz/abstractionUsage
Import individual modules or use presets for common workflows:
import { when, doTask } from '@bethel-nz/abstraction/cron';
import { everything } from '@bethel-nz/abstraction/presets';
// Schedule a daily task
when(
{ hour: 9, minute: 0 },
doTask(() => console.log('Morning sync'))
);
// Use everything preset
const { mapOver, eq } = everything;
const names = mapOver(
[{ name: 'Alice' }, { name: 'Bob' }],
(user) => user.name
); // ['Alice', 'Bob']Modules
core
Core utilities for functional programming and resilience.
eq<T>(a: T, b: T): boolean- Checks equality of two values.not(condition: boolean | (() => boolean)): boolean- Negates a condition.and(...conditions: (boolean | (() => boolean))[]): boolean- Returns true if all conditions are true.or(...conditions: (boolean | (() => boolean))[]): boolean- Returns true if any condition is true.pipe<T, U>(value: T, ...fns: ((arg: any) => any)[]): U- Composes functions left-to-right.attempt<T>(fn: () => T, fallback: T): T- Executes a function with a fallback on error.match<T, U>(value: T, cases: Array<{ when: (v: T) => boolean; then: (v: T) => U }>, defaultCase: (v: T) => U): U- Pattern matching.compose<T, U>(...fns: ((arg: any) => any)[]): (input: T) => U- Composes functions right-to-left.retry<T>(fn: () => T, options: { attempts: number; delay: number }): () => Promise<T>- Retries a function with delay.debounce<T extends (...args: any[]) => any>(fn: T, wait: number): (...args: Parameters<T>) => void- Debounces a function.throttle<T extends (...args: any[]) => any>(fn: T, wait: number): (...args: Parameters<T>) => void- Throttles a function.memoize<T extends (...args: any[]) => any>(fn: T): (...args: Parameters<T>) => ReturnType<T>- Memoizes a function.identity<T>(x: T): T- Returns the input unchanged.constant<T>(x: T): (...args: any[]) => T- Always returns the same value.noop(): void- Does nothing.once<T extends (...args: any[]) => any>(fn: T): (...args: Parameters<T>) => ReturnType<T> | undefined- Runs a function once.
cron
Temporal orchestration utilities.
when(time: TimeSpec, task: () => void, condition?: boolean | (() => boolean)): CancelToken- Schedules a task.every(interval: string, task: () => void, condition?: boolean | (() => boolean)): CancelToken- Runs a task at intervals.after(delay: number, task: () => void, condition?: boolean | (() => boolean)): CancelToken- Runs a task after a delay.at(date: Date, task: () => void, condition?: boolean | (() => boolean)): CancelToken- Runs a task at a specific date.ifThen(condition: boolean | (() => boolean), task: () => void): CancelToken- Runs a task if a condition is true.andThen(condition: boolean | (() => boolean), task: () => void): (c: boolean | (() => boolean)) => CancelToken- Chains conditions for ifThen.until(condition: boolean | (() => boolean), task: () => void): CancelToken- Runs a task until a condition is true.repeat(task: () => void, times: number): CancelToken- Repeats a task a specified number of times.withBackoff(task: () => Promise<void>, options: { maxAttempts: number; initialDelay: number; factor: number }): CancelToken- Runs a task with exponential backoff.runAll(tasks: (() => void)[], condition?: boolean | (() => boolean)): CancelToken- Runs multiple tasks in parallel.delay(ms: number): Promise<void>- Delays execution.interval(fn: () => void, ms: number): CancelToken- Runs a task at fixed intervals.timeout(fn: () => void, ms: number): Promise<void>- Runs a task after a delay with Promise resolution.cancelToken(): CancelToken- Creates a cancellation token.doTask(task: () => void): () => void- Executes a task immediately.
condition
Declarative conditional logic.
isEqual<T>(a: T, b: T): boolean- Alias for eq.ifEqual<T, U>(a: T, b: T, thenFn: () => U, elseFn: () => U): U- Executes based on equality.anyOf(...conditions: (boolean | (() => boolean))[]): boolean- Returns true if any condition is true.allOf(...conditions: (boolean | (() => boolean))[]): boolean- Returns true if all conditions are true.noneOf(...conditions: (boolean | (() => boolean))[]): boolean- Returns true if no conditions are true.ifThenElse<T>(condition: boolean | (() => boolean), thenFn: () => T, elseFn: () => T): T- Conditional execution.unless<T>(condition: boolean | (() => boolean), task: () => T): T | undefined- Executes unless a condition is true.guard<T>(condition: boolean | (() => boolean), fn: () => T): () => T | undefined- Guards a function with a condition.switchCase<T, U>(cases: Record<string, () => U>, defaultCase: () => U): (key: string) => U- Key-based case handling.caseOf<T, U>(...cases: Array<[predicate: (value: T) => boolean, fn: (value: T) => U]>): (value: T) => U- Predicate-based case handling.tryCatch<T>(fn: () => T, fallback: (error: unknown) => T): T- Handles errors with a fallback.
data
Data manipulation utilities.
filter<T>(data: T[], condition: (item: T) => boolean): T[]- Filters an array.mapOver<T, U>(data: T[], transform: (item: T) => U): U[]- Maps an array.reduce<T, U>(data: T[], reducer: (acc: U, item: T) => U, initial: U): U- Reduces an array.where<T>(data: T[], conditions: Array<(item: T) => boolean>): T[]- Filters with multiple conditions.select<T, K extends keyof T>(data: T[], keys: K[]): Pick<T, K>[]- Selects specific keys.groupBy<T, K extends string | number>(data: T[], keyFn: (item: T) => K): Record<K, T[]>- Groups by a key.findFirst<T>(data: T[], condition: (item: T) => boolean): T | undefined- Finds the first matching item.findAllEqual<T, K>(data: T[], key: keyof T, value: T[keyof T]): T[]- Finds all items with matching key-value.flatten<T>(arr: any[]): T[]- Deep flattens an array.unique<T>(arr: T[]): T[]- Removes duplicates.chunk<T>(arr: T[], size: number): T[][]- Splits into chunks.zip<T, U>(a: T[], b: U[]): [T, U][]- Pairwise combines arrays.deepMerge<T extends object, U extends object>(obj1: T, obj2: U): T & U- Deeply merges objects.
events
Event-driven programming utilities.
on(event: string, callback: (...args: any[]) => void): () => void- Listens for an event.once(event: string, callback: (...args: any[]) => void): () => void- Listens for an event once.emit(event: string, ...args: any[]): void- Emits an event.off(event: string, callback: (...args: any[]) => void): void- Removes an event listener.whenEvent(event: string, task: (...args: any[]) => void): () => void- Alias for on.onceEvent(event: string, task: (...args: any[]) => void): () => void- Alias for once.waitFor(event: string): Promise<any[]>- Waits for an event with a Promise.onceAny(events: string[], callback: (...args: any[]) => void): () => void- Triggers on the first of multiple events.pipeEvents(from: string, to: string): () => void- Forwards events.batchEmit(events: Array<[string, ...any[]]>): void- Emits multiple events.
fx
Side-effect utilities.
log<T>(label: string, value: T): T- Logs with a label.warn<T>(label: string, value: T): T- Warns with a label.error<T>(label: string, value: T): T- Errors with a label.tap<T>(fn: (value: T) => void): (value: T) => T- Executes a side-effect in a chain.
utils
General-purpose utilities.
deepClone<T>(obj: T): T- Deeply clones an object.isString(x: unknown): x is string- Type guard for strings.isArray(x: unknown): x is any[]- Type guard for arrays.isObject(x: unknown): x is object- Type guard for objects.isFunction(x: unknown): x is (...args: any[]) => any- Type guard for functions.
presets
Prebuilt bundles for common workflows.
everything- All module exports.dataFirst- Data manipulation utilities.fpStyle- Curried functional utilities.timing- Scheduling utilities.Abstractions- Type definition for the library.
Examples
import { when, doTask, every } from '@bethel-nz/abstraction/cron';
import { eq, and } from '@bethel-nz/abstraction/core';
import { mapOver, where } from '@bethel-nz/abstraction/data';
import { whenEvent, emit } from '@bethel-nz/abstraction/events';
import { log } from '@bethel-nz/abstraction/fx';
// Schedule a task
when(
{ hour: 9, minute: 0 },
doTask(() => console.log('Morning sync'))
);
// Conditional scheduling
const user = { isPremium: 'paid' };
every(
'5 seconds',
doTask(() => console.log('Status check')),
eq(user.isPremium, 'paid')
);
// Data manipulation
const users = [
{ name: 'Alice', role: 'admin' },
{ name: 'Bob', role: 'user' },
];
const admins = where(users, [(user) => eq(user.role, 'admin')]);
console.log(admins); // [{ name: 'Alice', role: 'admin' }]
// Event handling
whenEvent('userLogin', (user) => console.log(`User ${user.id} logged in`));
emit('userLogin', { id: 1, role: 'admin' });
// Side effects
mapOver(
users,
log('User', (user) => user.name)
); // Logs: [User] Alice, [User] BobDevelopment
- Build:
npm run build - Test:
npm run test - Generate Docs:
npm run docs
License
MIT