Skip to content

stopcock

Fast, composable TypeScript.

A focused set of TypeScript packages that play nicely together. Pipeable utilities sit alongside persistent collections, parsing, pattern matching, async tasks, HTTP, state, diffing, numerical tools, graphics, and dedicated testing and migration tooling.

import { pipe } from '@stopcock/fp'
import * as A from '@stopcock/fp/array'
type User = { name: string; active: boolean; score: number }
const top10 = pipe(
users,
A.filter((u: User) => u.active),
A.map((u: User) => ({ name: u.name, score: u.score })),
A.take(10),
)
import { pipe } from '@stopcock/fp'
import { now, add, format } from '@stopcock/date'
const nextWeek = pipe(now(), add(7, 'day'), format('YYYY-MM-DD'))
import { pipe } from '@stopcock/fp'
import { fromPromise, map, flatMap, retry, timeout, run } from '@stopcock/async'
const fetchUser = pipe(
fromPromise(() => fetch('/api/user')),
flatMap((res) => fromPromise(() => res.json())),
map((data) => data.name),
retry({ attempts: 3 }),
timeout(5000),
)
const name = await run(fetchUser)
import { diff, apply, invert } from '@stopcock/diff'
const before = { user: 'Tom', scores: [10, 20] }
const after = { user: 'Tom', scores: [10, 20, 30] }
const patch = diff(after)(before)
const restored = apply(invert(patch))(after)
import { create } from '@stopcock/state'
const store = create({ count: 0, name: 'Tom' })
store.subscribe(
(s) => s.count,
(next) => console.log(next),
)
store.set((s) => s.count, 1)
import { pipe } from '@stopcock/fp'
import { fromRGBA, resize, sharpen, contrast } from '@stopcock/img'
const thumbnail = (data: Uint8ClampedArray, w: number, h: number) =>
pipe(fromRGBA(data, w, h), resize(200, 200), (img) => sharpen(img), contrast(30))

@stopcock/fp Pipe, Option, Result, collections, algebra, optics, validation, and lazy Iter. @stopcock/fp-compiler Optional build-time lowering for portable, CSP-safe FP pipelines. @stopcock/fp-interop Explicit boundaries for foreign tagged values, Standard Schema, native protocols, and wire data. @stopcock/pattern Exhaustive structural matching, predicates, captures, and tagged-data dispatch. @stopcock/parser Typed parser combinators with precise source errors and stack-safe expression parsing. @stopcock/persistent Structurally shared vectors, maps, sets, queues, deques, and stacks. @stopcock/date Date arithmetic, formatting, parsing, timezones, and business day logic. @stopcock/async Lazy Task type with retry, timeout, concurrency limits, and cancellation via AbortSignal. @stopcock/fp-testing Deterministic law checks, edge-case data, and iterator cleanup probes. @stopcock/eslint-plugin-fp Flat-config rules for FP 2 migrations, focused imports, and pipeline performance. @stopcock/fp-codemod Conservative TypeScript-aware migrations from the FP 1 surface to FP 2. @stopcock/http Typed HTTP client with retry, timeout, dedup, and Task integration. @stopcock/autodiff Reverse-mode automatic differentiation for scalar, vector, and matrix values. @stopcock/la Typed-array vectors, matrices, decompositions, and optional acceleration hooks. @stopcock/signal Typed-array DSP kernels for FFTs, filters, convolution, resampling, and analysis. @stopcock/img Pixel-level image processing. Filters, convolution, resize, crop. @stopcock/diff Structural diffing, patching, composition, and rebasing for objects and arrays. @stopcock/state Reactive stores with fine-grained subscriptions, middleware, undo/redo, and devtools. @stopcock/color Color conversion, perceptual adjustment, contrast, gamut mapping, and CVD simulation. @stopcock/svg Typed procedural SVG nodes, paths, transforms, paint, filters, and rendering.

Compile the pipelines you’ve measured as hot

Section titled “Compile the pipelines you’ve measured as hot”

pipe runs each step in order — it doesn’t fuse anything by itself. For a pipeline you’ve actually measured as hot, the @stopcock/fp-compiler build plugin recognizes the shape and rewrites it into a single loop at build time, so take(10) stops after 10 hits without three full passes over the array. See Fusion.


Terminal window
bun add @stopcock/fp