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

@ppwcode/js-ts-oddsandends

v2.0.1

Published

TypeScript utility library: assertion functions and Joi schema test helpers

Readme

@ppwcode/js-ts-oddsandends

Small TypeScript utility library: assertion predicates, conditional-assert guards, and Joi schema test helpers.

Requirements

  • Node.js ≥ 24.16.0
  • Pure ESM — use import, not require.

Installation

npm install @ppwcode/js-ts-oddsandends

API

The assertion and conditional-assertion symbols are exported from the package root:

import {
  assert,
  ConditionViolation,
  containsNoDuplicates,
  isNatural,
  notNull,
  notUndefined,
  settings
} from '@ppwcode/js-ts-oddsandends'

expectSeriousSchema is available via a dedicated subpath import:

import { expectSeriousSchema } from '@ppwcode/js-ts-oddsandends/expectSeriousSchema'

Assertion predicates

Simple boolean predicates. Useful as arguments to assert or Joi .custom().

isNatural(i?: number): boolean

Returns true when i is undefined or a non-negative integer.

isNatural()   // true
isNatural(0)  // true
isNatural(7)  // true
isNatural(-1) // false
isNatural(Math.PI) // false

containsNoDuplicates<T>(arr: Array<T>): boolean

Returns true when the array contains no duplicate entries (compared with ===).

containsNoDuplicates([1, 2, 3]) // true
containsNoDuplicates([1, 2, 1]) // false

Conditional assertions

Runtime guards that throw ConditionViolation when an assertion fails. Guards are a no-op when settings.enabled is false (useful for disabling assertions in production if you choose to).

settings

settings.enabled       // default: true — all guards are active
settings.logViolations // default: false — log to console.error before throwing

assert<T, U extends T>(subject: T, assertion: (t: T) => t is U, message?: string): asserts subject is U

assert<T>(subject: T, assertion: (t: T) => boolean, message?: string): void

Throws ConditionViolation if assertion(subject) is falsy.

When assertion is a TypeScript type guard, TypeScript narrows the type of subject after the call. When assertion is a plain boolean predicate, the return is void and no narrowing occurs.

assert(count, Number.isInteger)
assert(index, i => i >= 0, 'index must be non-negative')

// with a type guard — subject is narrowed to string after this line:
assert(value, (v): v is string => typeof v === 'string')

notUndefined<T>(t?: T): asserts t is T

Asserts that t is not undefined. Narrows the type of t in-place.

const value: string | undefined = map.get(key)
notUndefined(value)
const definite: string = value  // TypeScript knows value is string here

notNull<T>(t: T | null): asserts t is T

Asserts that t is not null. Narrows the type of t in-place.

const node: Element | null = document.getElementById('root')
notNull(node)
node.classList.add('active')   // TypeScript knows node is Element here

ConditionViolation

Error subclass thrown when an assertion fails.


Schema test helper

Test helper for Joi schema validation. Works with mocha, jasmine, vitest (with globals: true), and node:test — the active framework is detected automatically.

Peer dependency: joi must be in your own dependencies or devDependencies. It is not bundled.

expectSeriousSchema(schema, failures, unknownNotAllowed?, context?, testApi?): void

Registers a suite of it() calls (nested inside a describe) that verify a Joi schema is well-formed:

  • is a recognised Joi schema
  • has a description
  • has at least one example value that validates
  • rejects every value in failures
  • optionally rejects unknown keys
import { expectSeriousSchema } from '@ppwcode/js-ts-oddsandends/expectSeriousSchema'
import { mySchema } from '../src/my-schema.js'

describe('mySchema', () => {
  expectSeriousSchema(mySchema, [null, undefined, 42, 'bad'])
})

Framework compatibility

expectSeriousSchema detects the active test framework at call time by checking globalThis.describe and globalThis.it. Supported configurations:

| Framework | Works automatically? | | --------- | -------------------- | | mocha | ✓ — injects describe/it as globals | | jasmine | ✓ — injects describe/it as globals | | vitest with globals: true | ✓ — injects describe/it as globals | | node:test | ✓ — used as fallback when no global describe/it is found | | vitest with globals: false (default) | ✗ — pass testApi explicitly (see below) |

testApi escape hatch

When vitest runs with its default config (globals: false), describe and it are not injected as globals and auto-detection falls back to node:test. Pass them explicitly as the last argument:

import { describe, it } from 'vitest'
import { expectSeriousSchema } from '@ppwcode/js-ts-oddsandends/expectSeriousSchema'
import { mySchema } from '../src/my-schema.js'

describe('mySchema', () => {
  expectSeriousSchema(mySchema, [null, undefined, 42, 'bad'], false, undefined, { describe, it })
})

Migrating from v1

See CHANGES.md for a full list of breaking changes.

Key actions:

  1. Switch from require() to import.
  2. Add joi to your own dependencies or devDependencies if you use expectSeriousSchema.
  3. Import assertion and conditional-assertion symbols from @ppwcode/js-ts-oddsandends; import expectSeriousSchema from @ppwcode/js-ts-oddsandends/expectSeriousSchema.

License

MIT — Copyright 2023–2026 PeopleWare n.v. See LICENSE.