0.2.0 • Published 9 months ago

@nodefill/util v0.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

node:util ponyfill

🧰 node:util for use anywhere

npm.io

✅ Mostly correct \ 📦 Works with Node.js, Deno, Bun, and the browser \ 🔬 Has TypeScript types \ ✨ Uses the node:util native package if available \ ⚠️ Distributed as CommonJS for widest compatibility

Installation

npm Yarn pnpm jsDelivr

You can install this package via npm, pnpm, or Yarn. It's also available on npm CDNs like jsDelivr and esm.sh if you want to import it straight from your browser!

npm install @nodefill/util
import {} from "https://esm.sh/@nodefill/util";
import {} from "https://esm.run/@nodefill/util";

If you're using Deno, you can use the new npm: specifier to import this package straight from npm, or use the esm.sh CDN which has support for Deno.

import {} from "npm:@nodefill/util";
import {} from "https://esm.sh/@nodefill/util";

Usage

Node.js Deno Browser Bun

You can import this package as though it were the normal node:util package! It will automatically use the native node:util package if it is available. Otherwise, you'll get some really nice shims that replicate the functionality. This is useful when authoring packages intended to be used in Node.js and the browser.

import { isArrayBuffer } from "@nodefill/util/types";
import { format } from "@nodefill/util";

console.log(isAnyArrayBuffer(new ArrayBuffer(1)));
//=> true
console.dir(format("Hello %s!", "world"));
//=> "Hello world!"

Limitations

⚠️ Some of the util.types.* functions in this package are loose (using plain-old Object.prototype.toString.call() or Symbol.toStringTag). Make sure you understand what each check does and whether or not it's looser than the native node:util/types function.

Some of the other utility functions like transferableAbortSignal() and transferableAbortController() don't really do much on non-Node.js platforms since Node.js is the only place you can do magic like that. They're included for API completeness.

Development

TypeScript Vitest

This package uses TypeScript! That makes it easy to co-locate types and code side-by-side without complicated /** @param */ declarations that get unweildy with larger projects.

To get started, clone this repository (or your fork) and run any of these commands to play around with the code:

npm test
npm run build
npm run build:docs

There's also a file naming convention where -default.ts files get exported via the default condition (via the exports field in package.json) and -node.ts files get exported via the node condition. This way, we can switch on "is this Node.js or something else?" statically instead of at runtime. This helps bundlers, loading performance, and more. The convention is that if there's more than one file for a given export, then explicitly suffix the file name with said export. For non-ambiguous exports (no conditions), we don't need to do this explicit naming (ex: lib/argsToTokens.ts doesn't have alternate implementations, so it's plain-old argsToTokens.ts).

Why use CommonJS? ESM is the onvious choice. The reason we still use CommonJS is because some packages may want a drop-in replacement for node:util/types when they use require(). Since ESM packages cannot be require()-ed, but CommonJS packages can be import()-ed, we use CommonJS for maximum compatibility. This may cause issues. If it is deemed such, this package may migrate to ESM-only in the future.

Why not distribute ESM and CJS versions? We could, but it would lead to the dual package hazard. The best way to support ESM and CJS at the same time is to write good CJS that imports well in ESM environments, possibly with a short index.mjs file to wrap the main CJS part. This is what we do.