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

@causalmap/filter-engine

v0.1.2

Published

Pure, dependency-free link-filter engine for causal maps: ordered structural filters (tags, label, path-tracing, frequency, combine-opposites, zoom/collapse and more), data in and data out.

Readme

@causalmap/filter-engine

Pure, dependency-free link-filter engine for causal maps. Give it a list of links and an ordered list of filter configs; get the filtered links back. No DOM, no database, no framework. Plain ES modules, Node 18+ or any modern browser.

This is the filtering core extracted from Causal Map. The code under src/ is a snapshot of the app's canonical engine, so its behaviour tracks the live product.

Licence

Source-available under the Functional Source License 1.1 (FSL-1.1-MIT): free to use, copy, modify and redistribute for any purpose except a competing use, that is, putting it into a product or service that substitutes for the Software or for Causal Map. Internal use, education, research and professional services are all permitted. Each release converts to the MIT licence two years after it is published. This is source-available rather than an OSI open-source licence until that conversion.

Install

npm install @causalmap/filter-engine

Quick start

import { applyOrderedLinkFilters } from '@causalmap/filter-engine'

const links = [
  { cause: 'training', effect: 'confidence', source_id: 's1', tags: 'outcome' },
  { cause: 'confidence', effect: 'income', source_id: 's1', tags: 'impact' },
  { cause: 'training', effect: 'income', source_id: 's2', tags: 'impact' },
]

const filters = [
  { type: 'tags', selectedTags: ['impact'] },
  { type: 'exclude-self-loops' },
]

const { rows, unsupported } = applyOrderedLinkFilters(links, filters /*, sources */)
// rows = the surviving links, in order; unsupported = any filter types this build does not handle

applyOrderedLinkFilters(links, filters, sources = []) runs the filters in array order and returns { rows, unsupported }. The optional third argument is the sources table (objects with at least id); it is only needed by filters that read source metadata.

The link object

A link is a plain object. The fields the engine reads:

  • cause, effect: factor labels (strings). The core of every link.
  • source_id: which source the link came from; used by frequency and path-tracing counts.
  • tags: string (comma-separated) or array, used by the tag filters.
  • any other column you attach (for example sentiment, or flattened source-group columns): read by the everything and source-groups filters via a resolved field name.

Extra fields you put on a link are preserved through filtering.

Filters

Each filter is { type, ...options }. Set enabled: false to skip one. Supported types:

| type | what it does | key options | |------|--------------|-------------| | label | keep links within N steps of factors matching a label | selectedLabels, stepsUp, stepsDown, traceThreads | | exclude-label | drop links whose cause/effect match labels | selectedLabels, matchMode, excludeAny | | tags | keep links matching any selected tag | selectedTags, matchMode | | exclude-tags | drop links matching selected tags | selectedTags, matchMode, excludeAny | | path-tracing | keep links on paths between two factor sets | see path tracing below | | link-frequency | keep the most or least frequent cause to effect pairs | which, mode, threshold | | factor-frequency | keep links whose factors are frequent enough | which, mode, threshold | | combine-opposites | merge negative variants into their positive label | sets flipped_* flags | | zoom | trim factor labels to a hierarchy level | level | | collapse | merge a set of labels into one | selectedLabels | | replace-brackets | rewrite bracketed label parts | | | source-groups | membership over a resolved source-group column | selectedField, selectedValues | | everything | membership over any resolved link column | selectedField, selectedValues | | exclude-self-loops | drop links where cause equals effect | |

matchMode is 'start' (default), 'anywhere', or 'exact'. Frequency mode is 'top' (default, keep the top threshold by count) or 'minimum' (keep count at or above threshold); which is 'sources' to count unique sources, otherwise it counts appearances.

Per-filter functions are also exported if you want to drive them yourself (applyTagsFilter, applyLinkFrequencyFilter, applyPathTracingFilter, and so on).

Path tracing

import { applyPathTracingFilter } from '@causalmap/filter-engine'

Keeps links lying on paths from one factor set to another within a step budget. Highlight helpers matchPathFactors and tracePaths are exported alongside it.

Reserved output fields

Some filters write fields onto the returned links. Do not strip these if you render downstream:

  • _recoded: { cause: { original, recoded }, effect: {...} }, set by zoom/collapse/replace-brackets; the earliest original is preserved. Used to display a renamed factor.
  • _recoded_cause / _recoded_effect: booleans, set by collapse and replace-brackets only.
  • flipped_cause / flipped_effect: booleans, set by combine-opposites and read by link-frequency bundling.

Host-resolved inputs

A few filters need a value the host application resolves and supplies:

  • everything / source-groups read link[filter.selectedField], so set selectedField to a real column before running (the app resolves friendly names to columns like sentiment or s_region).
  • link-frequency bundling can separate flipped opposite pairs. Pass applyLinkFrequencyFilter(links, filter, { separateFlippedBundles }) when driving it directly. It defaults to false, so a consumer without combine-opposites needs nothing.

Documentation

These filters are the engine behind the Causal Map app. To see what they do in context:

Provenance

Canonical source: webapp/js/filter-engine in the Causal Map app. src/ here is generated by sync-from-webapp.mjs and regenerated on every publish. The test suite under tests/ (run with npm test) includes the app's differential harnesses, which check this engine against a faithful copy of the app's filter logic across thousands of configurations.