npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lang-mini

v0.0.46

Published

General purpose JavaScript functions, extracted from jsgui. Also includes Evented_Class

Readme

lang-mini

Lang-mini is a lightweight, zero-runtime-dependency JavaScript toolkit that powers the core utilities, type system, and event infrastructure used across the wider jsgui3 ecosystem. It ships as a single file (lang-mini.js), works identically in Node.js and modern browsers, and focuses on highly-polymorphic utilities that remain ergonomic in plain JavaScript.

Key idea: Lang-mini combines small, composable helpers (iteration, cloning, truth maps) with advanced primitives (multi-function polymorphism, functional data types, grammar-based type inference) so that larger frameworks can build rich behavior without carrying heavy dependencies.


Why lang-mini?

  • Cross-environmentlang-mini.js auto-detects whether it's running in Node or the browser and exports the same API in both contexts via lib-lang-mini.js.
  • Polymorphic by defaultmfp() and fp() route calls using runtime signatures, letting you author concise yet type-aware functions.
  • Typed without TypeScriptFunctional_Data_Type, Type_Signifier, and Grammar provide runtime validation, parsing, and structural signatures that plug into UI and data layers.
  • Event-first architectureEvented_Class, eventify, field, and prop enable reactive data binding with tiny objects.
  • Battle-tested – A combined Jest + legacy test suite (118+ assertions) covers the core behaviors and prevents regressions.

Table of contents

  1. Quick start
  2. Installation
  3. Core concepts
  4. Reactive models & events
  5. Detailed feature guide
  6. API highlights
  7. Usage patterns & examples
  8. Asynchronous coordination
  9. Project layout
  10. Testing & development
  11. Status & roadmap notes
  12. License

Quick start

// CommonJS (Node.js ≥ 15)
const lang = require('lang-mini');
const { each, mfp } = lang;

each([1, 2, 3], (value, index) => {
	console.log(index, value * 2);
});

const describe = mfp({ name: 'describe', return_type: 'string' }, {
	's': (str) => `string(${str.length})`
});

console.log(describe('hello'));
// ESM / bundlers (Vite, Webpack, etc.)
import lang from 'lang-mini';

const pointDistance = lang.distance_between_points([[0, 0], [3, 4]]);
console.log(pointDistance); // → 5
<!-- Browser (UMD-style) -->
<script src="/path/to/lang-mini.js"></script>
<script>
  const { each, eventify } = window.lang;
  const state = eventify({});
  each(['a', 'b'], (item) => console.log(item));
</script>

Installation

Lang-mini is published to npm as a CommonJS module with no production dependencies.

npm install lang-mini

Node / bundlers

  • Entry point: lib-lang-mini.js re-exports everything from lang-mini.js.
  • Works with Node.js ≥ 15 (per package.json engines field).
  • When using ESM, import the default export: import lang from 'lang-mini';.
  • Tree-shaking is limited because the build is a single module; destructure the functions you need.

Browser via script tag

  1. Copy lang-mini.js into your project or serve it from your build pipeline.
  2. Include it before your scripts. It attaches a lang global.
  3. For bundlers, treat it as a standard CommonJS module and rely on your bundler's CJS support.

Core concepts

Collection helpers

  • each(collection, fn, [context]) – Unified iterator for arrays and objects. Returns a new array/object of collected results. Supports early exit via a third stop callback parameter.
  • clone(value) – Shallow clone for primitives, arrays, and objects. (Deep cloning is out of scope.)
  • arr_like_to_arr(arrayLike) – Converts arguments, DOM collections, and other array-like objects into real arrays.
  • Truth-map utilities:
    • get_truth_map_from_arr(array) converts an array into { value: true } object.
    • get_arr_from_truth_map(map) converts it back (stringifying keys).
    • get_map_from_arr(array) indexes values to their latest position.
  • is_array(value) and is_defined(value) provide robust guards that match the library's type semantics.

Functional polymorphism

  • mfp(config, handlers) – Multi-function polymorphism. Dispatches on signature strings built from runtime argument types (e.g. 'n,n', 's,[n]'). Supports verbs, nouns, and grammar metadata for descriptive error messages.
  • fp(handlers) – Lightweight version for simple polymorphic dispatch.
  • vectorify(fn) – Lifts a binary numeric function so it works element-wise over vectors/arrays.
  • distance_between_points([[x1, y1], [x2, y2]]) – Example of a vector-aware helper included in the library.

Type detection & signatures

  • tof(value) – Enhanced typeof returning array, null, undefined, etc.
  • tf(value) – Abbreviated signatures ('n', 's', 'b', 'a', 'o', 'u', 'N'). Used internally by mfp.
  • deep_sig(value, [maxDepth]) – Generates deterministic structural signatures such as '[{"a":n},{"b":n}]'. Useful for memoization and grammar inference.

Runtime type system

  • Functional_Data_Type – Define runtime types with validate, optional parse_string, and metadata. Frequently combined with field for model validation.
  • Type_Signifier & Type_Representation – Experimental utilities (exported via lib-lang-mini.js) for distinguishing what a value is from how it is represented. Useful when modelling complex domains (colors, dates, binary blobs).

Events & data binding

  • Evented_Class – Minimal event emitter with .on(event, handler) and .raise(event, data).
  • eventify(obj) – Mixes event methods into plain objects so they can emit (raise) and listen (on) to events.
  • field(obj, name, [typeOrDefault], [defaultOrTransform]) – Declares data-bound properties on eventified objects. Supports:
    • default values (field(obj, 'age', 21))
    • validation via Functional_Data_Type
    • transformation functions (field(obj, 'upperName', value => value.toUpperCase()))
    • change notifications (obj.raise('change', { name, old, value })).
  • prop – For binding properties across objects (used alongside eventify).

⚠️ Requirement: Always pass an object through eventify() before calling field() or prop(). Otherwise a TypeError is thrown (raise is not a function).

Grammar-driven inference (WIP)

  • Grammar – Describes structured data with singular/plural forms and resolves runtime signatures.
  • grammar.tof(value) – Infers the matching definition name (e.g. 'user_login').
  • grammar.sig(value) – Resolves plural forms ('users', 'locations').
  • Some deeper methods in Grammar are still marked NYI; expect evolution in future releases.

Reactive models & events

Reactive behavior is built into the library through Evented_Class, eventify, field, prop, and Functional_Data_Type. The combination lets you turn plain objects into observable models, add typed fields, and hook change events without pulling in a heavier framework. Check docs/Reactive_Models.md for the full guide and usage examples.


Detailed feature guide

The helpers highlighted under “core concepts” are unpacked at docs/Core_Features.md. That guide includes short examples for the collection utilities, polymorphic dispatch helpers, signature detectors, runtime type layer, and grammar/combinator building blocks.


API highlights

| Area | Key exports | Notes | |------|-------------|-------| | Collections | each, clone, arr_like_to_arr, get_truth_map_from_arr, get_map_from_arr, get_arr_from_truth_map | Consistent semantics between arrays and objects; helpers return transformed copies. | | Type detection | tof, tf, deep_sig | Signatures integrate with grammar and polymorphism features. | | Functional utilities | mfp, fp, vectorify, distance_between_points | mfp supports default handlers ('default' key) and grammar-aware error messages. | | Events | Evented_Class, eventify | Underpins field and prop; Evented_Class can be subclassed for richer components. | | Data binding | field, prop, Functional_Data_Type | Compose validation, parsing, defaults, and transformations with change events. | | Advanced types | Type_Signifier, Type_Representation | Experimental building blocks for rich type metadata. | | Combinatorics | combinations (alias: combos) | Cartesian product across nested arrays; stops early if any sub-array is empty. | | Async coordination | call_multi, call_multiple_callback_functions, Fns, Publisher | Mix callback ergonomics with promise-friendly utilities and readiness helpers. |

Full source documentation lives inline within lang-mini.js; search for function names to see implementation notes and historical commentary.


Usage patterns & examples

Iterating with each

const { each } = require('lang-mini');

const labelled = each({ a: 1, b: 2 }, (value, key) => `${key}:${value}`);
// labelled → { a: 'a:1', b: 'b:2' }

const doubleUp = each([1, 2, 3], (value, index, stop) => {
	if (value === 3) stop();
	return value * 2;
});
// doubleUp → [2, 4]

Polymorphism with mfp

const { mfp } = require('lang-mini');

const sum = mfp({ name: 'sum' }, {
	'n,n': (a, b) => a + b,
	'[n]': (arr) => arr.reduce((acc, n) => acc + n, 0),
	'default': (_, signature) => {
		throw new TypeError(`sum has no handler for signature ${signature}`);
	}
});

sum(2, 3);        // → 5
sum([1, 2, 3, 4]); // → 10

Creating validated, reactive models

const lang = require('lang-mini');
const person = lang.eventify({});

const IntegerType = new lang.Functional_Data_Type({
	name: 'integer',
	validate: Number.isInteger,
	parse_string: (value) => {
		const parsed = Number(value);
		return Number.isInteger(parsed) ? parsed : undefined;
	}
});

lang.field(person, 'name', (value) => value.trim());
lang.field(person, 'age', IntegerType, 18);

person.on('change', ({ name, old, value }) => {
	console.log(`${name} changed from ${old} → ${value}`);
});

person.name = ' Ada ';
person.age = '21';
// Console:
// name changed from undefined → Ada
// age changed from 18 → 21

Working with combinations

const { combinations } = require('lang-mini');

const colourways = combinations([
	['red', 'green'],
	['S', 'M', 'L'],
	['cotton', 'linen']
]);

console.log(colourways.length); // 12

Grammar-powered inference

const { Grammar } = require('lang-mini');

const geoGrammar = new Grammar({
	name: 'Geo',
	def: {
		coordinate: { def: ['number', 'number'], plural: 'coordinates' },
		route: { def: ['coordinate', 'coordinate'], plural: 'routes' }
	}
});

geoGrammar.tof([51.5, -0.1]);                 // → 'coordinate'
geoGrammar.sig([[51.5, -0.1], [40.7, -74]]);   // → 'route'
geoGrammar.sig([ [ [0,0], [1,1] ], [ [2,2], [3,3] ] ]); // → 'routes'

Tip: Some advanced grammar APIs remain marked NYI; consult inline comments before relying on them in production.


Asynchronous coordination

Lang-mini bundles a tiny but expressive concurrency helper stack for orchestrating callback-heavy workflows without pulling in a promise library. The primitives mirror the asynchronous utilities used throughout the historical jsgui projects and are now fully documented in docs/Async_Coordination.md.

call_multi & call_multiple_callback_functions

  • Accepts an array of work items where each item can be a bare function, [fn, params], [context, fn], or [fn, params, perTaskCallback].
  • Optional flags support:
    • Parallelism: pass lang.call_multi(tasks, parallelism, done) to limit concurrency.
    • Delays: pass both parallelism and delay to stagger invocations when throttling external systems.
    • Parameter echoing: lang.call_multi(tasks, done, true) returns [[params], result] tuples so you can rebuild association tables after asynchronous fan-outs.
  • Errors short-circuit the execution and bubble through the final callback, making it easy to surface failures while still allowing per-task callbacks to run.
const lang = require('lang-mini');

const work = [
        (cb) => setTimeout(() => cb(null, 'A'), 5),
        [({ message }, cb) => cb(null, message.toUpperCase()), [{ message: 'b' }]],
        [
                (value, cb) => cb(null, value * 2),
                [21],
                (err, doubled) => console.log('per-task:', doubled)
        ]
];

lang.call_multi(work, 2, 1, (err, results) => {
        if (err) throw err;
        console.log(results); // → ['A', { message: 'B' }, 42]
});

Fns.go

Fns(arr) wraps an array of functions and exposes a .go() helper that forwards to call_multi, preserving the same argument permutations. This is particularly useful when dynamically building pipelines:

const steps = lang.Fns([
        (cb) => readFile('./input.json', cb),
        (contents, cb) => cb(null, JSON.parse(contents)),
        (data, cb) => cb(null, transform(data))
]);

steps.go((err, [buffer, parsed, transformed]) => {
        if (err) throw err;
        console.log(transformed);
});

Publisher

Publisher extends Evented_Class and adds a when_ready getter that returns a promise resolving once the instance raises ready. The helper caches readiness so subsequent calls resolve synchronously, letting you bridge older callback code with modern async/await:

const publisher = new lang.Publisher();

async function ensureReady() {
        await publisher.when_ready; // waits until publisher.raise('ready')
        console.log('ready to emit');
}

ensureReady();
setTimeout(() => publisher.raise('ready'), 20);

Project layout

lang-mini/
├─ lang-mini.js           # Single-file implementation (~2800 lines)
├─ lib-lang-mini.js       # CommonJS re-export for consumers
├─ examples/              # Runnable usage samples (Node scripts)
├─ docs/                  # Additional design notes (e.g., Control_Dom)
├─ tests/                 # Jest + legacy test suites
│  ├─ *.test.js           # Modern Jest suites
│  ├─ all-test.js         # Legacy runner
│  └─ new-tests.js        # Legacy runner extension
├─ AI-NOTES.md            # Development notes and open questions
├─ TEST-SUMMARY.md        # Snapshot of recent test runs
└─ package.json           # Metadata, scripts, dev dependencies (jest, fnl)

Testing & development

Run the full suite (Jest + legacy tests):

npm test

Run only the Jest suites:

npm run test:jest

Run legacy suites (useful when iterating on old tests):

npm run test:legacy

Contribution tips

  • Keep lang-mini.js changes focused; it's a shared dependency across multiple projects.
  • Document behavioral observations or known issues in AI-NOTES.md before making large refactors.
  • Add or update tests under tests/ and ensure npm test passes before submitting PRs.

Status & roadmap notes

  • Version 0.0.40 (see package.json).
  • No production dependencies; fnl and jest are dev-only.
  • Several Grammar and advanced type-system methods are intentionally marked NYI; contributions welcome but coordinate via AI-NOTES.md first.
  • Roadmap items such as richer type representations and additional documentation live in AI-README.md and roadmap.md.
  • Keep up with the current focus areas in docs/Whats_Next.md, which consolidates the remaining gaps and suggested next steps for lang-mini.

License

MIT © James Vickers / Metabench