Options
All
  • Public
  • Public/Protected
  • All
Menu

hofkit

hofkit

hofkit (Higher Order Function toolKIT) is a modular functional utility library for JavaScript & TypeScript.

This library collects frequently rewritten experimental functional wrappers for commonly used utility functions. These wrappers emphasised functional concepts (e.g., higher order functions) to provide functional benefits (e.g., composition) whilst preserving compatibility with existing imperative approaches.

Through this flexiblity, the toolkit aims to be reusable across projects for a wide variety of uses ranging from array & object manipulation (e.g., filtering object entries) to concurrency-controlled Promises.

Additional benefits include builtin type support, environment-specific modules (i.e., featureGroups that group functions to separate dependencies), live-reloadable per-function test suites, and auto-generated live-reloadable documentation.

Features

Feature Details
Provides a library of functional utility functions Includes 164 core functions & 14 node-environment functions (as of initial release), that cover a variety of uses ranging from array & object manipulation (e.g., filtering object entries) to concurrency-controlled Promises
Compatible with function & imperative approaches Provides functional benefits (e.g., purity, composition) whilst remaining compatibility with imperative implementations
Interoperable with JavaScript & TypeScript -
Builtin TypeScript support for all functions All functions are written in TypeScript to generate bundled environment-specific declaration files
Typed return values for functional composition -
Auto-generated live-reloadable documentation Documentation is generated & live-reloadable for all featureGroup functions, which includes type signatures & any manual documentation
Modular environment-specific functions Environment-specific functions are grouped into individually importable featureGroup modules (e.g., core, node, etc.) to separate dependencies
Environment-specific per-function unit test suites All functions are easily testable via dedicated environment grouped live-reloadable test suites (totalling 180 test suites & 614 tests as of initial release)
Supports testing curried functions via command line See test:cli in Scripts
Zero dependencies A modular approach results in a small install file (127kB at initial release), where individual bundles can be used to separate & further reduce package sizes & separate dependencies
Consistent code via JavaScript & TypeScript linting Uses eslint-config-jsx to ensure consistent code

Usage

Install:

npm install hofkit

Using core functions in TypeScript:

import * as H from 'hofkit'; // Import all `core` functions.
// JavaScript: const H = require('hofkit');

import { titleCase } from H; // Named import.
// JavaScript: const { titleCase } = H;

titleCase('foo bar'); //=> 'Foo Bar'

// Typed return value: `toTitle: any => string`.
const toTitle = H.compose(
    titleCase,
    H.trim,
);
toTitle(' Foo-barBaz '); //=> 'Foo Bar Baz'

Using modular environment-specific functions (currently only node is supported), e.g., node functions:

import * as H from 'hofkit';
import * as HN from 'hofkit/dist/node'; // Import all `node` functions (requires Node environment).
import { readFile } from HN; // Named import.

// Using `async` IFFE for clarity but can be replaced by `H.promiseTryOr` to handle errors.
(async () => {
    // Writing to a file.
    await HN.writeFile('path/to/file')('foo');

    // Find existing paths.
    const filePaths = ['path1', 'path2', 'path3']; // Several file paths.
    const existingFilePaths = await H.promiseFilter(HN.pathExists);

    // Reading data for all existing files.
    let contents: string[] = [];
    const poolSize = 10;
    const onPoolComplete = (poolData: string) => [...contents, ...poolData]; // Flattens data from pools.
    const toFileContents = H.compose(
        H.promiseAll(poolSize, onPoolComplete), // Controlled concurrency.
        H.map(readFile)
    );
    toFileContents(existingFilePaths); //=> [['content1', ...], ...]

    // Overwriting all files.
    const writeFoo = (filePath: string) => HN.writeFile(filePath)('foo');
    const overwriteExistingFiles = H.compose(
        H.promiseAll(), // Uncontrolled concurrency;
        H.map(HN.writeFoo)
    );
    overwriteExistingFiles(filePaths);
})();

Documentation

Function documentation is available via the documentation website.

Screenshot of core documentation website:

Scripts

Script Info
test Run all tests
test:core Run all core feature group tests
test:node Run all node feature group tests
test <...test-names> Run tests matching test-names
test:watch Run all tests in watch mode
test:cli <functionName> <...argSets> Runs a function matching functionName with argSets (see runFunctionFromCli.ts)
test:data:reset Resets the test data directory (i.e., _testDataDir/) & its contents
docs:clean Remove existing docs
docs:build Output documentation to docs/
docs:build:serve Output & serve docs
docs:serve Serve existing docs in watch mode
docs:serve:open Open served docs
docs:watch Output docs in watch mode
docs:watch:serve Output & serve docs in watch mode
build:clean Removes the generated dist/ directory
build:featureGroupIndexes Updates all feature group index.ts files (i.e., updates exported functions, see updateFeatureGroupIndexes.ts)
build Generates the production dist/ directory & its contents (minified bundles, bundled declarations, etc.)
build:dev Development alternative to build
pack:clean Removes generated tarball files
pack Runs pack:clean before re-generating a tarball file containing npm required (e.g., package.json) & generated files (i.e., _dist/
pack:dry Same as pack but prints tarball file contents without generating the tarball file
deploy:pre Runs all pre-deploy scripts (e.g., test, build, pack, etc.)
deploy:major Runs deploy:pre before publishing an incremented major version
deploy:minor Runs deploy:pre before publishing an incremented minor version
deploy:patch Runs deploy:pre before publishing an incremented patch version
deploy Runs deploy:pre before publishing the current version

Development

Building:

  1. Build via build, which will clean (which additionally rebuilds indexes for all exposed hofkit functions (i.e., all core functions)) & build the dist files

Package Deployment:

  1. Pre-deployment checks can be run via deploy:pre, which checks git status, run testing, build docs, build the dist files, & pack the package
  2. Package contents can be previewed after pre-deployment via pack:dry
  3. Full deployment (requires login) can be run via deploy:<patch|minor|major>, which runs pre-deployment, versioning, & publication

Documentation Generation:

  1. Documentation can be generated via docs:build, which cleans, generates the changelog, & builds documentation from all hofkit functions
  2. Documentation can be accessed locally via docs:serve & navigating to localhost:8080 (e.g., via docs:serve:open in a separate shell)
  3. Live documentation generation via docs:watch & docs:watch:serve will hot reloads as source documentation updates

Documentation Deployment:

  1. The docs directory contains the generated documentation website files hence can be published & served from any HTML server

Gotchas

Builds:

  • All index.ts files for hofkit feature groups (e.g., core) are autogenerated via build:featureGroupIndexes hence shouldn't be edited

Documentation:

  • The changelog is generated via docs:changelog (hence shouldn't be edited) from VCS history & is currently added to documentation via a workaround (i.e., processes generated src/docPages/changelog.md into *.ts files into *.html files) as the documentation doesn't support adding paging non-code (e.g., *.md) pages

Future Plans

  • Fix JSDocs missing in prod
  • Complete remaining spec functions
  • Test async composition
  • Support web environments (e.g., browser, react, etc.)
  • Changelog