Discover which npm packages work in Cloudflare Workers. 395+ packages tested and working.
Showing runtime packages only. Build tools, CLI tools, and test frameworks are hidden by default.
Enable "Show build tools & incompatible" to see all 992 tested packages.
Showing 475 packages
OpenAPI/Swagger parser. parse() and dereference() work, but validate() fails because it uses ajv internally (code generation). Use for parsing specs, not validation.
import SwaggerParser from '@apidevtools/swagger-parser';
// Usage: Parse OpenAPI/Swagger specs (validation uses ajv which fails)
const spec = {
openapi: '3.0.0',
info: { title: 'My API', version: '1.0.0' },
paths: { '/users': { get: { responses: { '200': { description: 'OK' } } } } }
};
const parsed = await SwaggerParser.parse(spec);
return { success: true, result: { title: parsed.info.title } };
@emotion/core is deprecated and was replaced by @emotion/react in Emotion v11. Emotion is a CSS-in-JS library for React that requires browser/DOM APIs (document, window, HTMLElement) and React runtime for styling components. It's designed for client-side browser rendering with features like the css prop, styled components, theming, and dynamic styles. Not suitable for Workers serverless environment which has no DOM. For styling in Workers SSR, pre-generate styles at build time or use edge-compatible CSS solutions.
π‘ Alternative: @emotion/react (though also requires browser/React - neither work on Workers)
Works for server-side SVG generation, but DOM manipulation features require browser
import { library, icon } from '@fortawesome/fontawesome-svg-core';
import { faUser } from '@fortawesome/free-solid-svg-icons';
// Usage:
library.add(faUser);
const result = icon({ prefix: 'fas', iconName: 'user' });
const svg = result?.html?.[0];
return { success: svg?.includes('<svg') && svg?.includes('data-icon="user"'), result: { length: svg?.length } };
Icon definitions for Font Awesome, works in Workers
import { faUser, faHeart, faCheck } from '@fortawesome/free-solid-svg-icons';
// Usage:
const hasCorrectStructure = faUser.prefix === 'fas' &&
faUser.iconName === 'user' &&
Array.isArray(faUser.icon);
return { success: hasCorrectStructure, result: { icons: ['faUser', 'faHeart', 'faCheck'], prefix: faUser.prefix } };
Create executable GraphQL schemas. Merges type definitions and resolvers.
import { makeExecutableSchema } from '@graphql-tools/schema';
// Usage:
const typeDefs = 'type Query { hello: String }';
const resolvers = { Query: { hello: () => 'world' } };
const schema = makeExecutableSchema({ typeDefs, resolvers });
return { success: schema.getQueryType()?.name === 'Query', result: 'Schema created' };
SQLite client for Turso and libSQL. Use with D1: createClient({ url: process.env.DATABASE_URL })
import { createClient } from '@libsql/client';
// Usage:
// Test client creation and API surface
const client = createClient({ url: 'libsql://fake-host.turso.io' });
return { success: typeof client.execute === 'function' && typeof client.batch === 'function', result: 'libSQL client created' };
MessagePack binary serialization - typically 25-50% smaller than JSON. Supports typed arrays, Maps, and custom extensions. Great for efficient data transfer between Workers and clients/APIs.
import { encode, decode } from '@msgpack/msgpack';
export default {
async fetch(request) {
// Encode complex data
const data = {
name: 'User',
nested: { foo: 'bar', num: 42 },
tags: ['worker', 'test'],
binary: new Uint8Array([1, 2, 3, 4, 5])
};
const encoded = encode(data);
const decoded = decode(encoded);
// MessagePack is ~25% smaller than JSON
const jsonSize = JSON.stringify(data).length;
const msgpackSize = encoded.byteLength;
return Response.json({
decoded,
compression: `${msgpackSize}/${jsonSize} bytes (${(msgpackSize/jsonSize*100).toFixed(0)}%)`
});
}
};
Serverless Postgres driver for Neon. Works on Workers with HTTP connection pooling.
import { neon } from '@neondatabase/serverless';
// Usage:
const sql = neon('postgresql://user:pass@host/db');
return { success: typeof sql === 'function', result: 'Neon client created' };
GitHub API client - works on Workers
import { Octokit } from '@octokit/rest';
// Usage:
const octokit = new Octokit();
const { data } = await octokit.rest.repos.get({ owner: 'cloudflare', repo: 'workers-sdk' });
return { success: data.name === 'workers-sdk', result: data.name };
Serverless MySQL driver for PlanetScale. Works on Workers with HTTP connection.
import { connect } from '@planetscale/database';
// Usage:
const conn = connect({ url: 'mysql://user:pass@host/db' });
return { success: typeof conn.execute === 'function', result: 'PlanetScale client created' };
HTTP content negotiation library. Parses Accept headers for content-type negotiation.
import accepts from 'accepts';
// Usage:
const accept = accepts(request);
const type = accept.type(['json', 'html']);
return { success: true, result: { preferredType: type } };
JavaScript parser producing AST. Supports ES2022+ including private fields, optional chaining, nullish coalescing, and ESM syntax. Useful for code analysis, transformation, or building dev tools in Workers.
import * as acorn from 'acorn';
export default {
async fetch(request) {
// Parse ES modules with modern syntax
const code = `
import { foo } from './bar';
const obj = { a: 1, ...other };
const fn = async () => await fetch('/api');
class Foo { static bar = 42; }
`;
const ast = acorn.parse(code, {
ecmaVersion: 2022,
sourceType: 'module'
});
return Response.json({
type: ast.type,
statements: ast.body.length,
firstNode: ast.body[0].type
});
}
};
ZIP creation works perfectly. Extraction/decompression fails with 'Memory limit exceeded' error due to zlib constraints in Workers. Use for creating ZIPs only - for extraction, consider streaming or using R2/external storage.
import AdmZip from 'adm-zip';
// Creating ZIP works:
const zip = new AdmZip();
zip.addFile('hello.txt', Buffer.from('Hello from Workers!'));
zip.addFile('data.json', Buffer.from(JSON.stringify({ test: true })));
const zipBuffer = zip.toBuffer();
// Return as downloadable ZIP:
return new Response(zipBuffer, {
headers: {
'Content-Type': 'application/zip',
'Content-Disposition': 'attachment; filename="archive.zip"'
}
});
AMQP client for RabbitMQ. Loads but requires TCP connection. Use Cloudflare Queues for message queuing in Workers.
import amqp from 'amqplib';
// Usage: Create credentials (actual connection needs TCP to RabbitMQ)
const credentials = amqp.credentials.plain('user', 'pass');
return { success: credentials.mechanism === 'PLAIN', result: { mechanism: credentials.mechanism, note: 'Use Cloudflare Queues instead' } };
apollo-client v2 is deprecated. It was the old GraphQL client for React apps, split into multiple npm packages (apollo-client, apollo-cache-inmemory, apollo-link-http, graphql-tag). Primarily designed for browser/React environments. Replaced by the unified @apollo/client v3+ package.
π‘ Alternative: @apollo/client
apollo-link is the core interface/base class for Apollo Client v2's modular link architecture (apollo-link, apollo-link-http, apollo-link-ws, apollo-link-state, etc.). Published 6 years ago (2018) as part of the split Apollo Client v2 system where each transport/middleware was a separate package. Apollo Client v3+ (released 2020) unified all these packages into a single @apollo/client package with better TypeScript support, improved caching, and modern React hooks. This package is deprecated infrastructure - use @apollo/client instead.
π‘ Alternative: @apollo/client
Part of deprecated Apollo Client v2 modular architecture (apollo-client, apollo-link, apollo-link-http, apollo-cache-inmemory). Apollo Client v3+ unified these packages into a single @apollo/client package with better TypeScript support, improved developer experience, and modern GraphQL features. apollo-link-http was the HTTP transport layer for sending GraphQL queries over HTTP in Apollo v2.
π‘ Alternative: @apollo/client
Built-in Node.js assert module
Extra assertions on top of Node.js assert module - provides type checking utilities
import assert from 'assert-plus';
// Usage:
assert.string('hello', 'value');
assert.number(42, 'value');
assert.object({ foo: 'bar' }, 'value');
return { success: true, result: 'All assertions passed' };
Async utilities for control flow
import async from 'async';
// Usage:
const results = await async.parallel([
async () => 1,
async () => 2,
async () => 3,
]);
return { success: results[0] === 1 && results[1] === 2 && results[2] === 3, result: results };
Retry async operations with exponential backoff. Supports bail() to abort retries on fatal errors, configurable timeout/factor. Perfect for resilient API calls in Workers.
import retry from 'async-retry';
export default {
async fetch(request) {
// Retry with exponential backoff
const result = await retry(async (bail, attemptNumber) => {
const response = await fetch('https://api.example.com/data');
// Use bail() to stop retrying on fatal errors
if (response.status === 401) {
bail(new Error('Unauthorized - no point retrying'));
return;
}
if (!response.ok) throw new Error(`Attempt ${attemptNumber} failed`);
return response.json();
}, {
retries: 5,
minTimeout: 100,
maxTimeout: 1000,
factor: 2
});
return Response.json(result);
}
};
Async form validation library - commonly used with Ant Design forms
import Schema from 'async-validator';
// Usage:
const descriptor = {
name: { type: 'string', required: true, message: 'Name is required' },
age: { type: 'number', min: 0, max: 120 }
};
const validator = new Schema(descriptor);
const result = await validator.validate({ name: 'Alice', age: 30 });
return { success: true, result };
aws-sdk (v2) is the legacy monolithic AWS SDK for JavaScript - now deprecated and replaced by AWS SDK v3. v2 requires node:punycode which isn't available in Workers' nodejs_compat. More importantly, AWS SDK v2 is a massive monolithic package importing ALL AWS services (~50MB+), making it unsuitable for edge/serverless. AWS SDK v3 (@aws-sdk/client-s3, @aws-sdk/client-dynamodb, @aws-sdk/client-sqs, etc.) is modular, tree-shakeable, and specifically designed to work in browser/edge environments including Workers. Use the specific @aws-sdk/client-* packages for the AWS services you need.
π‘ Alternative: @aws-sdk/client-* (AWS SDK v3)
Error: No such module "node:punycode".
Popular HTTP client. Works on Workers with nodejs_compat. Consider using native fetch() for simpler use cases.
π‘ Alternative: built-in: fetch
import axios from 'axios';
// Make HTTP requests
const response = await axios.get('https://api.example.com/data');
return { success: response.status === 200, data: response.data };
JavaScript base64 encoder/decoder. Workers also has native atob()/btoa() functions.
import base64 from 'base-64';
// Usage:
const encoded = base64.encode('Hello, World!');
const decoded = base64.decode(encoded);
return { success: decoded === 'Hello, World!', result: { encoded, decoded } };
Base64 encoding/decoding
import * as base64 from 'base64-js';
// Usage:
const text = 'Hello World!';
const bytes = new TextEncoder().encode(text);
const encoded = base64.fromByteArray(bytes);
const decoded = base64.toByteArray(encoded);
const result = new TextDecoder().decode(decoded);
return { success: result === text, result: { encoded, decoded: result } };
HTTP Basic Authentication parser - parses Authorization header to extract credentials
import auth from 'basic-auth';
// Usage:
// Simulate an HTTP request with Basic Auth header
const credentials = btoa('user:pass'); // Base64 encode 'user:pass'
const mockRequest = {
headers: {
authorization: `Basic ${credentials}`
}
};
const parsed = auth(mockRequest);
return { success: parsed?.name === 'user' && parsed?.pass === 'pass', result: parsed };
bcrypt is a native module with C++ bindings that requires node:os and won't work in Workers. Use bcryptjs (pure JS implementation) or @cloudflare/workers-bcrypt (optimized for Workers) instead.
π‘ Alternative: bcryptjs or @cloudflare/workers-bcrypt
Error: No such module "node:os".
bcrypt-nodejs is deprecated and unmaintained since 2013. The package explicitly recommends using bcrypt or bcryptjs instead (see https://github.com/kelektiv/node.bcrypt.js/wiki/bcrypt-vs-brypt.js). While bcrypt-nodejs is pure JavaScript and might technically work, the recommended alternative bcryptjs works perfectly on Workers and is actively maintained.
π‘ Alternative: bcryptjs
Pure JavaScript bcrypt implementation - perfect alternative to native bcrypt which doesn't work on Workers. Both sync and async methods work. Use saltRounds of 10-12 for good security/performance balance.
import bcrypt from 'bcryptjs';
export default {
async fetch(request) {
const password = 'mypassword123';
// Hash password (both sync and async work)
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync(password, salt);
// Or use async versions
const asyncHash = await bcrypt.hash(password, 10);
// Verify password
const isValid = bcrypt.compareSync(password, hash);
const asyncValid = await bcrypt.compare(password, asyncHash);
return Response.json({ hash, isValid, asyncValid });
}
};
Arbitrary-precision decimal arithmetic
import Big from 'big.js';
// Usage:
const x = new Big('0.1');
const y = new Big('0.2');
const sum = x.plus(y);
return { success: sum.toString() === '0.3', result: sum.toString() };
Arbitrary-precision decimal and non-decimal arithmetic
import BigNumber from 'bignumber.js';
// Usage:
const x = new BigNumber('0.1');
const y = new BigNumber('0.2');
const sum = x.plus(y);
return { success: sum.toString() === '0.3', result: sum.toString() };
Bitcoin BIP39 mnemonic code library. Generate and validate seed phrases.
import * as bip39 from 'bip39';
// Usage:
const mnemonic = bip39.generateMnemonic();
const isValid = bip39.validateMnemonic(mnemonic);
return { success: isValid, result: { wordCount: mnemonic.split(' ').length } };
Buffer List - collect and manage multiple buffers as one contiguous buffer.
import bl from 'bl';
// Usage:
const list = new bl();
list.append(Buffer.from('Hello '));
list.append(Buffer.from('World'));
const result = list.toString();
return { success: result === 'Hello World', result: { text: result, length: list.length } };
Feature-rich Promise library with utilities like map (with concurrency), filter, reduce, props, some, any, delay, and more. All features work on Workers.
import Promise from 'bluebird';
export default {
async fetch(request) {
// Promise.map with concurrency control
const items = [1, 2, 3, 4, 5];
const mapped = await Promise.map(items, async (n) => {
await Promise.delay(10);
return n * 2;
}, { concurrency: 2 });
// Promise.props - resolve object of promises
const props = await Promise.props({
a: Promise.resolve(1),
b: Promise.delay(10).then(() => 2)
});
// Promise.filter, Promise.reduce
const filtered = await Promise.filter(items, n => n % 2 === 0);
const sum = await Promise.reduce(items, (acc, n) => acc + n, 0);
return Response.json({ mapped, props, filtered, sum });
}
};
Big number library for arbitrary-precision integer arithmetic.
import BN from 'bn.js';
// Usage:
const a = new BN('1234567890123456789');
const b = new BN('9876543210987654321');
const sum = a.add(b);
return { success: sum.toString() === '11111111101111111110', result: sum.toString() };
Express middleware for parsing request bodies. Use with httpServerHandler from cloudflare:node for Express compatibility, or use native Request.json()/Request.text() for simpler cases.
import bodyParser from 'body-parser';
// Usage: Express middleware for parsing request bodies
// Use with httpServerHandler from cloudflare:node for Express apps
const jsonParser = bodyParser.json();
const urlencodedParser = bodyParser.urlencoded({ extended: true });
return { success: true, result: 'Middleware created' };
HTTP-friendly error objects with proper status codes, messages, and error payloads. Supports notFound(), unauthorized(), badRequest(), forbidden(), conflict(), internal(), teapot(), and more. Use Boom.isBoom() to detect Boom errors.
import Boom from 'boom';
export default {
async fetch(request) {
const url = new URL(request.url);
try {
if (url.pathname === '/protected') {
throw Boom.unauthorized('Authentication required');
}
if (url.pathname === '/missing') {
throw Boom.notFound('Resource not found', { id: 123 });
}
return Response.json({ message: 'OK' });
} catch (error) {
if (Boom.isBoom(error)) {
return Response.json(error.output.payload, {
status: error.output.statusCode,
headers: error.output.headers
});
}
throw error;
}
}
};
Rate limiter and task scheduler. Control concurrency and request rates.
import Bottleneck from 'bottleneck';
// Usage:
const limiter = new Bottleneck({ maxConcurrent: 1, minTime: 100 });
const result = await limiter.schedule(() => Promise.resolve('done'));
return { success: result === 'done', result };
Base58 encoding/decoding - commonly used in Bitcoin, IPFS, and other blockchain applications.
import bs58 from 'bs58';
// Usage:
const bytes = new Uint8Array([1, 2, 3, 4, 5]);
const encoded = bs58.encode(bytes);
const decoded = bs58.decode(encoded);
return { success: decoded.length === 5 && decoded[0] === 1, result: { encoded, decoded: Array.from(decoded) } };
MongoDB BSON serialization with full support for ObjectId, Binary, UUID, Date, and other BSON types. Use for MongoDB-compatible data or efficient binary serialization. EJSON support for JSON-compatible output.
import { BSON, ObjectId, Binary, UUID, serialize, deserialize } from 'bson';
export default {
async fetch(request) {
// Create MongoDB-compatible documents
const doc = {
_id: new ObjectId(),
name: 'Document',
data: new Binary(Buffer.from('binary data')),
uuid: new UUID(),
created: new Date()
};
// Serialize/deserialize
const bsonData = serialize(doc);
const restored = deserialize(bsonData);
// EJSON for JSON-compatible output
const ejson = BSON.EJSON.stringify(doc);
return Response.json({ restored, ejson });
}
};
btoa() is a native Web API function for base64 encoding (binary-to-ASCII) that's already built into Cloudflare Workers. The 'btoa' npm package was created as a polyfill for Node.js environments that didn't have btoa natively. Workers provides native btoa()/atob() functions - no package installation needed. Simply use: btoa('hello') to encode, atob('aGVsbG8=') to decode.
Node.js Buffer polyfill. Use built-in Workers Buffer or Uint8Array when possible.
import { Buffer } from 'buffer';
// Usage:
const buf = Buffer.from('hello world', 'utf-8');
const hex = buf.toString('hex');
const base64 = buf.toString('base64');
return { success: hex.length === 22 && base64.length === 16, result: { hex, base64 } };
Bunyan is a JSON logging library for Node.js that requires unsupported Node.js APIs. Fails with 'No such module "node:os"' - the os module (for hostname, platform info) is not available in Workers even with nodejs_compat. Bunyan relies on Node.js-specific APIs like os.hostname(), process.pid, and filesystem streams for logging.
π‘ Alternative: pino
Error: No such module "node:os".
Convert byte values to/from human-readable strings (e.g., "1MB" β 1048576).
import bytes from 'bytes';
// Usage:
const parsed = bytes('1MB');
const formatted = bytes(1048576);
return { success: parsed === 1048576 && formatted === '1MB', result: { parsed, formatted } };
Convert strings to camelCase format.
import camelCase from 'camelcase';
// Usage:
const result1 = camelCase('foo-bar');
const result2 = camelCase('foo_bar');
const result3 = camelCase('foo bar');
return { success: result1 === 'fooBar' && result2 === 'fooBar' && result3 === 'fooBar', result: { result1, result2, result3 } };
CBOR (Concise Binary Object Representation) encoding/decoding.
π‘ Alternative: @msgpack/msgpack (MessagePack is similar binary format)
import { encode, decode } from 'cbor';
// Usage:
const data = { name: 'test', values: [1, 2, 3] };
const encoded = encode(data);
const decoded = decode(encoded);
return { success: decoded.name === 'test', result: { decoded, encodedLength: encoded.length } };
BDD/TDD assertion library. Works on Workers but primarily for test frameworks.
import { expect } from 'chai';
// Usage:
expect(2 + 2).to.equal(4);
expect('hello').to.be.a('string');
expect([1, 2, 3]).to.have.lengthOf(3);
return { success: true, result: 'All assertions passed' };
Random data generator for testing, mocking APIs, and development. Generates names, emails, addresses, GUIDs, IPs, colors, sentences, and more. Supports seeding for reproducible results.
import Chance from 'chance';
export default {
async fetch(request) {
const chance = new Chance();
// Seed for reproducible results
const seeded = new Chance(12345);
return Response.json({
person: {
name: chance.name(),
email: chance.email(),
phone: chance.phone(),
address: chance.address(),
city: chance.city()
},
misc: {
guid: chance.guid(),
ip: chance.ip(),
url: chance.url(),
color: chance.color({ format: 'hex' })
},
// Seeded gives same result every time
seededName: seeded.name()
});
}
};
import { camelCase, snakeCase } from 'change-case';
// Usage:
const camel = camelCase('hello world');
const snake = snakeCase('helloWorld');
return { success: true, result: { camel, snake } };
jQuery-like HTML parsing and manipulation. Perfect for web scraping, HTML transformation, and extracting data from webpages on Workers. Supports full CSS selectors.
import * as cheerio from 'cheerio';
export default {
async fetch(request) {
// Fetch and parse a webpage
const response = await fetch('https://example.com');
const html = await response.text();
const $ = cheerio.load(html);
// Extract data with jQuery-like selectors
const title = $('title').text();
const h1 = $('h1').text();
const links = $('a').map((i, el) => $(el).attr('href')).get();
// Manipulate HTML
$('h1').addClass('scraped').text('Modified');
return Response.json({ title, h1, links });
}
};
Color manipulation library for parsing (hex, rgb, hsl, lab), converting between formats, generating scales/gradients, mixing colors, and checking WCAG contrast ratios for accessibility.
import chroma from 'chroma-js';
export default {
async fetch(request) {
// Parse and manipulate colors
const color = chroma('#3498db');
return Response.json({
original: color.hex(),
darken: color.darken().hex(),
brighten: color.brighten().hex(),
rgb: color.rgb(),
hsl: color.hsl(),
luminance: color.luminance(),
// Generate color scales
gradient: chroma.scale(['#fafa6e', '#2A4858']).colors(5),
// Color mixing
mix: chroma.mix('red', 'blue', 0.5).hex(),
// WCAG contrast check
contrast: chroma.contrast('white', '#3498db')
});
}
};
Decorator-based validation. Decorators require TypeScript with experimentalDecorators and special bundler config. Consider using zod instead for simpler setup.
π‘ Alternative: zod
import { ValidationError } from 'class-validator';
// Usage: Decorators need TypeScript experimentalDecorators
const err = new ValidationError();
err.property = 'email';
err.constraints = { isEmail: 'must be valid email' };
return { success: true, result: { note: 'Use zod for Workers - decorators need special bundler config' } };
Conditionally join CSS class names together. Useful for dynamic styling.
import classNames from 'classnames';
// Usage:
const classes = classNames('btn', { active: true, disabled: false }, 'primary');
return { success: classes === 'btn active primary', result: classes };
CLI table formatting. Limited usefulness in Workers but works.
import Table from 'cli-table';
// Usage:
const table = new Table({ head: ['Name', 'Age'] });
table.push(['John', '30'], ['Jane', '25']);
const str = table.toString();
return { success: str.includes('John') && str.includes('30'), result: str.substring(0, 100) };
Deep clone objects including dates, functions, and nested structures. Works on Workers. Alternative: structuredClone() for simpler cases.
π‘ Alternative: built-in: structuredClone
import clone from 'clone';
const original = { a: 1, b: { c: 2 } };
const cloned = clone(original);
cloned.b.c = 999;
// original.b.c is still 2
return { success: original.b.c === 2, cloned };
Generator-based async control flow. Supports sequential operations, parallel arrays/objects. Modern async/await is preferred for new code, but co still works for legacy codebases.
import co from 'co';
export default {
async fetch(request) {
// Generator-based control flow
const result = await co(function* () {
// Sequential async operations
const response = yield fetch('https://httpbin.org/json');
const data = yield response.json();
// Parallel with arrays
const [a, b, c] = yield [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
];
return { title: data.slideshow.title, sum: a + b + c };
});
return Response.json(result);
}
};
Color manipulation and conversion library. Works well in Workers.
import Color from 'color';
// Usage:
const color = Color('rgb(255, 0, 0)');
const hex = color.hex();
const lightened = color.lighten(0.5).hex();
return { success: hex === '#FF0000', result: { hex, lightened } };
ES2015 template literal tag functions for string manipulation (stripIndent, oneLine, html, etc.).
import { stripIndent, oneLine, html } from 'common-tags';
// Usage:
const multiline = stripIndent`
Hello
World
!
`;
const single = oneLine`
This will be
on one line
`;
const markup = html`<div>Hello</div>`;
return {
success: multiline === 'Hello\n World\n !' && single.includes('This will be on one line'),
result: { multiline, single, markup }
};
Simple event emitter for creating event-based APIs with on/off/emit methods.
import Emitter from 'component-emitter';
// Usage:
const emitter = new Emitter();
let result = null;
emitter.on('test', (data) => { result = data; });
emitter.emit('test', 'hello');
return { success: result === 'hello', result };
Express middleware for gzip/deflate compression. Works with Express via httpServerHandler.
π‘ Alternative: CompressionStream (built-in Web API) or Hono's compress() middleware
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import compression from 'compression';
const app = express();
app.use(compression());
app.get('/test', (req, res) => {
res.json({ data: 'x'.repeat(1000) });
});
app.listen(3000);
export default httpServerHandler({ port: 3000 });
import concat from 'concat-stream';
// Usage:
const { Writable } = await import('stream');
const stream = concat((data) => {
return { success: data.toString() === 'hello', result: data.toString() };
});
stream.write('hello');
stream.end();
return { success: true, result: 'stream created' };
Extensible HTTP server framework (predecessor to Express). Works with httpServerHandler.
π‘ Alternative: Hono or itty-router
Error: Unexpected token ':'
import { httpServerHandler } from 'cloudflare:node';
import connect from 'connect';
const app = connect();
app.use((req, res) => {
res.end('Hello from Connect!');
});
app.listen(3000);
export default httpServerHandler({ port: 3000 });
Flash message middleware for Express. Works with express-session via httpServerHandler.
Error: Package connect-flash needs manual test configuration - do not use generic Object.keys() test
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import session from 'express-session';
import flash from 'connect-flash';
const app = express();
app.use(session({ secret: 'secret', resave: false, saveUninitialized: true }));
app.use(flash());
app.get('/set', (req, res) => { req.flash('info', 'Hello!'); res.json({ set: true }); });
app.get('/get', (req, res) => res.json({ messages: req.flash('info') }));
app.listen(3000);
export default httpServerHandler({ port: 3000 });
Middleware to proxy requests through index.html for SPA routing. Works with Express via httpServerHandler.
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import history from 'connect-history-api-fallback';
const app = express();
app.use(history({ rewrites: [{ from: /^\/api\/.*$/, to: ctx => ctx.parsedUrl.pathname }] }));
app.get('/index.html', (req, res) => res.send('<html>SPA</html>'));
app.get('/api/test', (req, res) => res.json({ api: true }));
app.listen(3000);
export default httpServerHandler({ port: 3000 });
import contentType from 'content-type';
// Usage:
const result = contentType.parse('text/html; charset=utf-8');
return { success: result.type === 'text/html', result };
Converts source maps between different formats (JSON, base64, inline comments).
import { fromObject, fromJSON } from 'convert-source-map';
// Usage:
const map = { version: 3, sources: ['foo.js'], mappings: 'AAAA' };
const converter = fromObject(map);
const json = converter.toJSON();
const parsed = fromJSON(json);
return { success: parsed.toObject().version === 3, result: parsed.toObject() };
HTTP cookie parsing/serialization
import cookie from 'cookie';
// Usage:
const result = cookie.parse('foo=bar; baz=qux');
return { success: result.foo === 'bar' && result.baz === 'qux', result };
Express middleware for parsing cookies. Works with Express via httpServerHandler.
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import cookieParser from 'cookie-parser';
const app = express();
app.use(cookieParser('secret'));
app.get('/test', (req, res) => {
res.cookie('test', 'value', { signed: true });
res.json({ cookies: req.signedCookies });
});
app.listen(3000);
export default httpServerHandler({ port: 3000 });
import { sign, unsign } from 'cookie-signature';
// Usage:
const val = sign('hello', 'secret');
const result = unsign(val, 'secret');
return { success: result === 'hello', result };
CORS middleware for Express/Connect. Works with httpServerHandler.
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import cors from 'cors';
const app = express();
app.use(cors({ origin: 'https://example.com', methods: ['GET', 'POST'] }));
app.get('/api', (req, res) => res.json({ data: 'test' }));
app.listen(3000);
export default httpServerHandler({ port: 3000 });
CRC (Cyclic Redundancy Check) checksums - supports CRC1, CRC8, CRC16, CRC24, CRC32
import { crc32 } from 'crc';
// Usage:
const checksum = crc32('hello world');
return { success: typeof checksum === 'number' && checksum === 0x0d4a1185, result: '0x' + checksum.toString(16) };
create-hash is a Node.js crypto.createHash polyfill (part of crypto-browserify) that provides hash digest functions (md5, sha1, sha256, sha512, etc.). Fails with 'Cannot read properties of undefined (reading 'slice')' due to Buffer implementation incompatibilities. Workers has the built-in Web Crypto API (crypto.subtle.digest) which is the modern standard for hashing and provides better performance.
π‘ Alternative: Web Crypto API (crypto.subtle.digest) - built-in
Node.js cron job scheduler for running scheduled tasks (e.g., CronJob('0 0 * * *', callback)). Requires child_process for spawning tasks. Workers has built-in Scheduled Events (Cron Triggers) for scheduled tasks - use scheduled handler: export default { scheduled(event, env, ctx) { ... } }
π‘ Alternative: Cloudflare Workers Scheduled Events (Cron Triggers) - built-in
Error: No such module "node:child_process".
Universal fetch API polyfill
import fetch from 'cross-fetch';
// Usage:
const result = await fetch('https://httpbin.org/get');
const data = await result.json();
return { success: result.ok, result: { status: result.status } };
Crypto library for hashing (SHA256, MD5) and encryption (AES). Works on Workers. Consider Web Crypto API for better performance.
π‘ Alternative: built-in: crypto
import CryptoJS from 'crypto-js';
// Hash a string
const hash = CryptoJS.SHA256('hello world').toString();
// Encrypt/decrypt
const encrypted = CryptoJS.AES.encrypt('secret', 'password').toString();
const decrypted = CryptoJS.AES.decrypt(encrypted, 'password').toString(CryptoJS.enc.Utf8);
return { success: true, hash, decrypted };
Full-featured CSV parsing and generation. Supports headers, custom delimiters (TSV), quoted values, escaped characters, and both sync and streaming APIs.
import { parse, stringify } from 'csv/sync';
export default {
async fetch(request) {
// Parse CSV with headers as column names
const csvData = 'name,age,city\nAlice,30,NYC\nBob,25,LA';
const records = parse(csvData, { columns: true, skip_empty_lines: true });
// Generate CSV from objects
const data = [{ id: 1, product: 'Widget', price: 9.99 }];
const csv = stringify(data, { header: true });
// TSV support with custom delimiter
const tsv = 'name\tvalue\nfoo\t100';
const tsvRecords = parse(tsv, { columns: true, delimiter: '\t' });
return Response.json({ records, csv, tsvRecords });
}
};
Collision-resistant ID generator. Creates sortable, URL-safe IDs. Includes cuid.slug() for shorter IDs and validation functions. Works on Workers with nodejs_compat.
import cuid from 'cuid';
export default {
async fetch(request) {
// Generate collision-resistant IDs
const id = cuid();
// Shorter slug version for URLs
const slug = cuid.slug();
// Validate IDs
const isValid = cuid.isCuid(id);
const isSlug = cuid.isSlug(slug);
// Generate multiple unique IDs
const ids = Array.from({ length: 5 }, () => cuid());
return Response.json({ id, slug, isValid, isSlug, ids });
}
};
D3 array manipulation library with statistical functions (min, max, mean, median), array transformations (group, bin, bisect), and data operations.
import { min, max, mean, median, extent, group } from 'd3-array';
// Usage:
const data = [1, 5, 2, 8, 3];
const minVal = min(data);
const maxVal = max(data);
const meanVal = mean(data);
const medianVal = median(data);
const extentVal = extent(data);
const grouped = group([{key: 'a', val: 1}, {key: 'b', val: 2}, {key: 'a', val: 3}], d => d.key);
return { success: minVal === 1 && maxVal === 8 && meanVal === 3.8 && medianVal === 3, result: { minVal, maxVal, meanVal, medianVal, extentVal, grouped: grouped.size } };
D3 scales for mapping data values to visual ranges. Includes linear, logarithmic, power, time, and categorical scales for data visualization.
import { scaleLinear, scaleLog, scalePow, scaleTime } from 'd3-scale';
// Usage:
const linear = scaleLinear().domain([0, 10]).range([0, 100]);
const log = scaleLog().domain([1, 10]).range([0, 100]);
const pow = scalePow().exponent(2).domain([0, 10]).range([0, 100]);
const time = scaleTime().domain([new Date(2020, 0, 1), new Date(2021, 0, 1)]).range([0, 100]);
const linearVal = linear(5);
const logVal = log(5);
const powVal = pow(5);
const timeVal = time(new Date(2020, 6, 1));
return { success: linearVal === 50 && logVal > 0 && powVal === 25 && timeVal > 0, result: { linearVal, logVal, powVal, timeVal } };
D3 shape generators for SVG path data. Provides line(), area(), pie(), arc(), and more for creating data-driven shapes and charts.
import { line, area, pie, arc } from 'd3-shape';
// Usage:
const lineGenerator = line().x((d, i) => i * 10).y(d => d);
const linePath = lineGenerator([10, 20, 30, 20, 10]);
const areaGenerator = area().x((d, i) => i * 10).y0(0).y1(d => d);
const areaPath = areaGenerator([10, 20, 30, 20, 10]);
const pieGenerator = pie();
const pieData = pieGenerator([1, 2, 3]);
const arcGenerator = arc().innerRadius(0).outerRadius(100);
const arcPath = arcGenerator(pieData[0]);
return { success: typeof linePath === 'string' && typeof areaPath === 'string' && pieData.length === 3 && typeof arcPath === 'string', result: { linePath: linePath.substring(0, 20), pieAngles: pieData.map(d => [d.startAngle, d.endAngle]) } };
import { format, parseISO } from 'date-fns';
// Usage:
const date = parseISO('2026-01-08');
const formatted = format(date, 'yyyy-MM-dd');
return { success: formatted === '2026-01-08', result: formatted };
import dayjs from 'dayjs';
// Usage:
const date = dayjs('2026-01-08');
const formatted = date.format('YYYY-MM-DD');
return { success: formatted === '2026-01-08', result: formatted };
Delays function calls until a set time elapses after the last invocation.
import debounce from 'debounce';
// Usage:
let callCount = 0;
const debouncedFn = debounce(() => { callCount++; }, 100);
debouncedFn();
debouncedFn();
debouncedFn();
// Wait for debounce delay
await new Promise(resolve => setTimeout(resolve, 150));
return { success: callCount === 1, result: callCount };
Lightweight debugging utility with namespace-based logging. Works in Workers - debug output appears in console/logs.
import debug from 'debug';
// Create namespaced loggers
const logApp = debug('app:main');
const logHttp = debug('app:http');
// Enable namespaces
debug.enable('app:*');
export default {
async fetch(request) {
const url = new URL(request.url);
logApp('Request: %s %s', request.method, url.pathname);
logHttp('Headers: %O', Object.fromEntries(request.headers));
return Response.json({ debugEnabled: debug.enabled('app:main') });
}
};
Converts camelCase strings to lowercase with custom separator (default underscore).
import decamelize from 'decamelize';
// Usage:
const result = decamelize('unicornRainbow');
const custom = decamelize('unicornRainbow', { separator: '-' });
return { success: result === 'unicorn_rainbow' && custom === 'unicorn-rainbow', result: { result, custom } };
Arbitrary-precision decimal arithmetic
import Decimal from 'decimal.js';
// Usage:
const x = new Decimal(0.1);
const y = new Decimal(0.2);
const result = x.plus(y).toString();
return { success: result === '0.3', result };
Calculate deep differences between objects. Captures changes (added, deleted, edited, array changes) and can apply/revert changes.
import { diff, applyChange } from 'deep-diff';
// Usage:
const lhs = { name: 'Alice', age: 30, city: 'NYC' };
const rhs = { name: 'Alice', age: 31, city: 'LA' };
const differences = diff(lhs, rhs);
const hasChanges = differences && differences.length === 2;
const ageChanged = differences.some(d => d.path[0] === 'age' && d.lhs === 30 && d.rhs === 31);
const cityChanged = differences.some(d => d.path[0] === 'city' && d.lhs === 'NYC' && d.rhs === 'LA');
return { success: hasChanges && ageChanged && cityChanged, result: differences };
Deep equality comparison for objects
import deepEqual from 'deep-equal';
// Usage:
const result1 = deepEqual({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } });
const result2 = deepEqual({ a: 1 }, { a: 2 });
return { success: result1 && !result2, result: { result1, result2 } };
Recursively extend objects
import deepExtend from 'deep-extend';
// Usage:
const result = deepExtend({ a: 1, b: { c: 2 } }, { b: { d: 3 } });
return { success: result.a === 1 && result.b.c === 2 && result.b.d === 3, result };
Deep merge of objects
import deepmerge from 'deepmerge';
// Usage:
const result = deepmerge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });
return { success: result.a === 1 && result.b.c === 2 && result.b.d === 3, result };
Deprecation warning utility for Node.js modules. Works in Workers for issuing console warnings about deprecated API usage.
import depd from 'depd';
const deprecate = depd('my-module');
function oldFunction() {
deprecate('oldFunction() is deprecated');
return 'result';
}
export default {
async fetch(request) {
const result = oldFunction();
return Response.json({ result, message: 'Check console for deprecation warning' });
}
};
Destroy a stream safely, handling different stream types.
import destroy from 'destroy';
import { Readable } from 'node:stream';
// Usage:
const stream = new Readable({ read() {} });
destroy(stream);
return { success: stream.destroyed, result: { destroyed: stream.destroyed } };
Serialize JavaScript values (including Date, RegExp, Map, Set)
import { stringify, parse } from 'devalue';
// Usage:
const obj = { a: 1, b: new Date('2026-01-10'), c: /test/ };
const str = stringify(obj);
const result = parse(str);
return { success: result.a === 1 && result.b instanceof Date, result };
Text diff implementation (characters, words, lines, JSON)
import * as diff from 'diff';
// Usage:
const result = diff.diffChars('hello', 'hallo');
return { success: result.length > 0 && result.some(p => p.added || p.removed), result };
Money/currency handling with precision
import Dinero from 'dinero.js';
// Usage:
const price = Dinero({ amount: 500, currency: 'USD' });
const total = price.add(Dinero({ amount: 200, currency: 'USD' }));
return { success: total.getAmount() === 700, result: total.toFormat('$0,0.00') };
discord.js is a Discord bot library that requires persistent WebSocket connections to Discord's Gateway API for real-time events (listening to messages, presence updates, voice state changes, etc.). Designed for long-running Node.js bot applications that maintain always-on Gateway connections. Workers is a stateless serverless environment without support for persistent WebSocket connections or long-running processes. The main discord.js package uses @discordjs/ws for Gateway WebSocket management which is incompatible with Workers' request/response lifecycle. Note: The discord.js website shows 'Powered by Cloudflare Workers' because their documentation site is hosted on Workers, not because the bot library works on Workers. For Discord interactions on Workers, use @discordjs/rest (REST API only) or @discordjs/core (thin wrapper for REST + webhook-based interactions). These packages support slash commands, webhooks, and REST API calls without requiring Gateway connections.
π‘ Alternative: @discordjs/rest or @discordjs/core for REST-only Discord interactions (slash commands, webhooks)
DOMPurify requires a real DOM (window/document) which Workers doesn't have. isomorphic-dompurify also doesn't work (isSupported: false). Use sanitize-html instead - it's a pure string-based HTML sanitizer that works perfectly on Workers without DOM dependencies.
π‘ Alternative: sanitize-html
TypeScript ORM with SQL-like syntax
import { sql } from 'drizzle-orm';
// Usage:
const query = sql`SELECT * FROM users WHERE id = ${123}`;
return { success: query.queryChunks.length > 0, result: 'SQL query built' };
DEPRECATED package (no longer maintained since 2020). Official legacy Elasticsearch JavaScript client for connecting to Elasticsearch servers via HTTP REST API. Replaced by @elastic/elasticsearch (the new official client). The old client is no longer maintained and users are strongly advised to migrate to the new client. While theoretically an HTTP REST client could work in Workers, this legacy package is unmaintained and has compatibility issues. Original error 'Cannot read properties of undefined (reading 'bold')' occurred due to outdated dependencies and lack of maintenance.
π‘ Alternative: @elastic/elasticsearch (new official client) - may work with Workers, needs testing
Pure JavaScript elliptic curve cryptography library for ECDSA, EdDSA, and ECDH operations. Supports curves: secp256k1, p192, p224, p256, p384, p521, curve25519, ed25519. Fails with 'Unexpected token ":"' parse error when bundled for Workers - likely due to code incompatible with Workers runtime. Workers has the built-in Web Crypto API (crypto.subtle) which provides native elliptic curve cryptography (ECDSA with P-256/P-384/P-521, ECDH) with better performance and security than pure JavaScript implementations.
π‘ Alternative: Web Crypto API (crypto.subtle.sign/verify with ECDSA, crypto.subtle.deriveKey/deriveBits with ECDH) - built-in
Error: Unexpected token ':'
Simple email validation
import validator from 'email-validator';
// Usage:
const valid = validator.validate('test@example.com');
const invalid = validator.validate('notanemail');
return { success: valid && !invalid, result: { valid, invalid } };
Character encoding conversion
import { convert } from 'encoding';
// Usage:
const result = convert('hello', 'UTF-8');
return { success: result.toString() === 'hello', result: result.toString() };
ES6 Promise polyfill (mostly unnecessary in Workers)
import { Promise } from 'es6-promise';
// Usage:
const p = new Promise((resolve) => resolve('ok'));
const result = await p;
return { success: result === 'ok', result };
Converts callback-based functions to ES6 Promises.
import { promisify } from 'es6-promisify';
// Usage:
// Create a callback-based function
const callbackFn = (a, b, callback) => {
setTimeout(() => callback(null, a + b), 10);
};
// Convert to promise-based
const promiseFn = promisify(callbackFn);
const result = await promiseFn(2, 3);
return { success: result === 5, result };
import escapeHtml from 'escape-html';
// Usage:
const escaped = escapeHtml('<script>alert("xss")</script>');
return { success: escaped.includes('<'), result: escaped };
Escape special regex characters
import escapeStringRegexp from 'escape-string-regexp';
// Usage:
const result = escapeStringRegexp('foo.bar*baz');
return { success: result === 'foo\\.bar\\*baz', result };
JavaScript parser (ECMAScript parser)
import { parseScript } from 'esprima';
// Usage:
const ast = parseScript('const x = 42;');
return { success: ast.type === 'Program', result: ast.type };
Generate HTTP ETags for caching. Create strong/weak ETags from content.
import etag from 'etag';
// Usage:
const body = 'Hello World';
const tag = etag(body);
return { success: tag.startsWith('"') || tag.startsWith('W/'), result: { etag: tag } };
DEPRECATED package - last published 6 years ago (2018). ethereumjs-tx is the legacy Ethereum transaction library for creating, signing, and serializing Ethereum transactions. Used for constructing raw Ethereum transactions with Transaction class that handles nonce, gasPrice, gasLimit, to, value, data fields. Supports EIP-155 replay protection, chain/hardfork configuration (mainnet, ropsten, custom networks), transaction signing with private keys via sign() method, and serialization for broadcast to Ethereum nodes. Part of the EthereumJS ecosystem (ethereumjs-util, ethereumjs-common, ethereumjs-vm). Official deprecation message: 'New package name format for new versions: @ethereumjs/tx. Please update.' The package has been superseded by @ethereumjs/tx which has modern features, active maintenance, and improved TypeScript support. Similar Ethereum transaction libraries include ethers.js (more complete, recommended), web3.js (older alternative), viem (modern TypeScript alternative).
π‘ Alternative: @ethereumjs/tx (official successor) - may work with Workers, needs testing
DEPRECATED - old package (last published 2022). Official successor is @ethereumjs/util (v10.x, actively maintained, published 2025-11). The old package provides Ethereum utility functions: account/address operations (creation, validation, conversion, checksums), byte manipulation helpers, hash functions (Keccak-256), signature operations (signing, validation, recovery), constants (KECCAK256_NULL_S, etc.), and re-exports BN.js and rlp. Modern @ethereumjs/util has better TypeScript support, improved APIs, and active maintenance with latest Ethereum specs. Part of EthereumJS ecosystem (ethereumjs-tx β @ethereumjs/tx, ethereumjs-common β @ethereumjs/common, etc.). Dependencies include create-hash, ethereum-cryptography, bn.js, rlp - all pure JS crypto. Similar Ethereum utilities include ethers.js utils, web3.js utils, viem utils.
π‘ Alternative: @ethereumjs/util (v10.x, official successor) - may work with Workers, needs testing
Stream utilities and helpers
import es from 'event-stream';
// Usage:
const results = [];
const stream = es.through(function(data) { results.push(data); this.emit('data', data); });
stream.write('test');
return { success: results[0] === 'test', result: results };
Enhanced EventEmitter with wildcards and namespaces
import { EventEmitter2 } from 'eventemitter2';
// Usage:
const emitter = new EventEmitter2();
let called = false;
emitter.on('test', () => { called = true; });
emitter.emit('test');
return { success: called, result: { called } };
Fast EventEmitter implementation
import EventEmitter from 'eventemitter3';
// Usage:
const emitter = new EventEmitter();
let value = '';
emitter.on('event', (msg) => { value = msg; });
emitter.emit('event', 'hello');
return { success: value === 'hello', result: { value } };
Node.js EventEmitter - available in Workers
import { EventEmitter } from 'events';
// Usage:
const ee = new EventEmitter();
let count = 0;
ee.on('test', () => { count++; });
ee.emit('test');
return { success: count === 1, result: { count } };
Node.js web framework. Works on Workers with httpServerHandler from cloudflare:node. Requires nodejs_compat flag.
π‘ Alternative: Hono (most Express-like, fastest), itty-router (tiny, simple), Toucan (Sentry-like routing), or workers-router (official Cloudflare routing helper)
Error: Unexpected strict mode reserved word
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
const app = express();
app.use(express.json());
app.get('/',(req, res) => res.json({ message: 'Express on Workers!' }));
app.post('/echo', (req, res) => res.json({ received: req.body }));
app.listen(3000);
export default httpServerHandler({ port: 3000 });
Express middleware for session management
import session from 'express-session';
// Usage:
const middleware = session({ secret: 'test', resave: false, saveUninitialized: true });
return { success: typeof middleware === 'function', result: 'session middleware created' };
Object extension utility
import extend from 'extend';
// Usage:
const result = extend({ a: 1 }, { b: 2 }, { c: 3 });
return { success: result.a === 1 && result.b === 2 && result.c === 3, result };
Shallow object extension utility. Like Object.assign() but with more flexible API for merging multiple objects.
import extend from 'extend-shallow';
// Usage:
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const obj3 = { c: 5, d: 6 };
const result = extend(obj1, obj2, obj3);
const success = result.a === 1 && result.b === 3 && result.c === 5 && result.d === 6;
return { success, result };
DEPRECATED package (last published 2022) - the original faker.js library by Marak for generating fake data (names, addresses, emails, phone numbers, lorem ipsum, dates, etc.). Package was abandoned in January 2022 after the maintainer deleted the repository in protest. The community immediately forked the project to @faker-js/faker which is now the official maintained successor with active development, bug fixes, new locales, TypeScript improvements, and better tree-shaking. The old 'faker' package (v6.6.6) still works for basic fake data generation but receives no updates, security patches, or new features. Used extensively in: test data generation (seeding databases, populating fixtures), development/demos (mock data for UI development), API mocking (generating realistic API responses), and data anonymization. @faker-js/faker has identical API for easy migration (faker.name.findName(), faker.internet.email(), faker.address.city(), etc.), better TypeScript support with improved type definitions, more locales (70+ languages), active community maintenance with regular updates, and modern bundler optimization. Similar fake data generators include chance.js (alternative API), casual (simpler alternative), json-schema-faker (generates from JSON schemas).
π‘ Alternative: @faker-js/faker (official community-maintained fork) - may work with Workers, needs testing
Fast deep equality comparison for objects and arrays
import equal from 'fast-deep-equal';
// Usage:
const a = { x: 1, y: { z: 2 } };
const b = { x: 1, y: { z: 2 } };
const c = { x: 1, y: { z: 3 } };
const result1 = equal(a, b);
const result2 = equal(a, c);
return { success: result1 === true && result2 === false, result: { equal: result1, notEqual: result2 } };
Fast XML parser, builder, and validator. Supports attributes, CDATA, namespaces, and various XML formats (RSS, SOAP, etc.). No DOM required - pure string parsing.
import { XMLParser, XMLBuilder, XMLValidator } from 'fast-xml-parser';
export default {
async fetch(request) {
// Parse XML to JSON
const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@_' });
const xml = '<catalog><book id="1"><title>JS Guide</title></book></catalog>';
const parsed = parser.parse(xml);
// Build XML from JSON
const builder = new XMLBuilder({ ignoreAttributes: false, attributeNamePrefix: '@_' });
const built = builder.build({ root: { item: [{ '@_id': '1', name: 'Item' }] } });
// Validate XML
const isValid = XMLValidator.validate(xml);
return Response.json({ parsed, built, isValid });
}
};
Fast pure-JS compression library. Supports GZIP, DEFLATE, ZLIB, and ZIP. Both creation and extraction work (unlike adm-zip). Use sync versions (gzipSync, zipSync) in Workers.
import { gzipSync, gunzipSync, zipSync, unzipSync, strToU8, strFromU8 } from 'fflate';
export default {
async fetch(request) {
// GZIP compression
const text = 'Hello '.repeat(100);
const gzipped = gzipSync(strToU8(text));
const ungzipped = strFromU8(gunzipSync(gzipped));
// Create ZIP archive
const archive = zipSync({
'hello.txt': strToU8('Hello World'),
'data.json': strToU8(JSON.stringify({ test: true }))
});
// Extract ZIP
const extracted = unzipSync(archive);
return Response.json({
gzipRatio: (gzipped.length / text.length * 100).toFixed(1) + '%',
zipFiles: Object.keys(extracted)
});
}
};
ASCII art text generator. Must preload fonts using importable-fonts - async font loading does not work in Workers.
import figlet from 'figlet';
import standard from 'figlet/importable-fonts/Standard.js';
// Usage: Must preload fonts
figlet.parseFont('Standard', standard);
const ascii = figlet.textSync('Hi!', { font: 'Standard' });
return { success: ascii.length > 0, result: { ascii } };
Detects file types from file signatures (magic bytes). Works with Uint8Array buffers. Useful for validating uploads, detecting MIME types.
import { fileTypeFromBuffer } from 'file-type';
// Usage:
// PNG magic bytes: 89 50 4E 47 0D 0A 1A 0A (with some extra bytes for the tokenizer)
const pngBytes = new Uint8Array([
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x15, 0xC4
]);
const result = await fileTypeFromBuffer(pngBytes);
return { success: result?.ext === 'png' && result?.mime === 'image/png', result };
Human-readable file sizes. Use named import: import { filesize } from filesize
import { filesize } from 'filesize';
filesize(1024); // '1.02 kB'
Express/Connect final handler for ending middleware chains. Works with httpServerHandler - correctly handles 404s and errors.
π‘ Alternative: Use Hono or itty-router for error handling
import { httpServerHandler } from 'cloudflare:node';
import { createServer } from 'node:http';
import finalhandler from 'finalhandler';
const server = createServer((req, res) => {
const done = finalhandler(req, res);
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Hello!' }));
} else {
done(); // 404 for unknown routes
}
});
server.listen(3000);
export default httpServerHandler({ port: 3000 });
Flatten/unflatten nested objects. Use named imports: import { flatten, unflatten } from flat
import { flatten, unflatten } from 'flat';
const flat = flatten({ a: { b: 1 } });
// { 'a.b': 1 }
Multipart/form-data encoding
import FormData from 'form-data';
// Usage:
const form = new FormData();
form.append('key', 'value');
return { success: true, result: 'FormData created' };
Formidable is a Node.js form parsing library for handling multipart/form-data, especially file uploads, in traditional Node.js HTTP servers (http.createServer). Requires node:os module which is not supported in Workers nodejs_compat (only crypto, fs, path, buffer, stream, events, util, http, https, net, dns, zlib, timers, url, assert, process, diagnostics_channel, async_hooks are supported). Designed for Node.js request/response objects and filesystem-based temporary file storage during upload processing. Workers uses Request/Response objects and has better alternatives for form parsing.
π‘ Alternative: Workers Request.formData() API (native multipart/form-data parsing built-in), or busboy (lower-level multipart parser that may work with Workers)
Error: No such module "node:os".
Parse X-Forwarded-For header
import forwarded from 'forwarded';
// Usage:
const req = {
headers: { 'x-forwarded-for': '192.168.1.1, 10.0.0.1' },
connection: { remoteAddress: '127.0.0.1' }
};
const addresses = forwarded(req);
return { success: Array.isArray(addresses) && addresses.length === 3, result: addresses };
Extracts YAML front matter from markdown files. Commonly used in static site generators.
import fm from 'front-matter';
// Usage:
const content = `---
title: Hello World
date: 2026-01-09
tags: [test, markdown]
---
# Article Content
This is the body of the article.
`;
const parsed = fm(content);
return {
success: parsed.attributes.title === 'Hello World' && parsed.body.includes('Article Content'),
result: { attributes: parsed.attributes, bodyLength: parsed.body.length }
};
Node.js fs module is available but operates on a virtual in-memory filesystem. No persistent storage - files are lost between requests. Use R2, KV, or D1 for persistent storage.
import * as fs from 'node:fs';
// Usage:
const result = { existsSync: typeof fs.existsSync === 'function', readFileSync: typeof fs.readFileSync === 'function' };
return { success: result.existsSync && result.readFileSync, result };
DEPRECATED package (last updated 2017). Official deprecation message: 'Use mz or fs-extra^3.0 with Promise Support'. This was a promise wrapper for Node.js filesystem operations (fs.readFile, fs.writeFile, etc.) before native fs.promises API existed in Node.js. Modern Node.js (10+) has native fs.promises built-in. Workers has limited virtual filesystem via nodejs_compat - no persistent storage. For file storage in Workers, use R2 (object storage), KV (key-value), or D1 (database).
π‘ Alternative: R2 for object storage, KV for key-value, D1 for database, or native fs.promises in modern Node.js (if targeting Node.js)
Generic resource pooling. Useful for managing database connections or API clients.
import { createPool } from 'generic-pool';
const pool = createPool({
create: async () => ({ id: Date.now() }),
destroy: async (r) => {}
}, { max: 10 });
const resource = await pool.acquire();
await pool.release(resource);
DEPRECATED! Package renamed to @octokit/rest. The 'github' package is the old GitHub API client library that has been superseded by @octokit/rest which is the official GitHub REST API client for Node.js/browser maintained by GitHub. Provides comprehensive GitHub API integration: repositories (create/read/update/delete), issues/PRs (list/create/comment/merge), users/orgs (profiles/memberships), gists (create/update), notifications, search, git data operations. @octokit/rest has better TypeScript support, active maintenance, OAuth2/token authentication, pagination helpers, rate limit handling, and webhooks support. Works in Node.js and browsers with fetch API. Similar GitHub API libraries include @octokit/graphql (GraphQL API), octonode (alternative client), github-api (community client).
π‘ Alternative: @octokit/rest (official successor, actively maintained by GitHub) - works on Workers with fetch API
Error: 'github' has been renamed to '@octokit/rest' (https://git.io/vNB11)
Polyfill for accessing the global object across environments. Returns globalThis in Workers. Useful for cross-environment compatibility.
import global from 'global';
// Usage:
// global is a polyfill for accessing global variables across environments
// It returns the global object (globalThis in Workers)
const hasGlobal = typeof global === 'object';
const hasGlobalThis = global === globalThis;
return { success: hasGlobal && hasGlobalThis, result: { type: typeof global, isGlobalThis: hasGlobalThis } };
googleapis is Google's official Node.js client library for accessing 200+ Google APIs (Drive, Gmail, YouTube, Calendar, etc.) with OAuth2, API keys, and service account authentication. Error "No such module 'node:child_process'" indicates it requires child_process (non-functional stub in Workers) for internal operations like gRPC connections or auth flows. The monolithic googleapis package bundles all Google API clients (200+ APIs, 200 MB unpacked) with shared auth infrastructure. Designed for traditional Node.js servers with full Node.js API access. For Google APIs in Workers, use better alternatives: (1) @googleapis/* scoped packages (e.g., @googleapis/drive, @googleapis/gmail) - individual API packages that may work better in Workers with tree-shaking and smaller bundles, needs testing per API; (2) Direct Google REST APIs - call Google API endpoints directly using Workers' native fetch() with manual OAuth2/API key auth headers for full control; (3) @google-cloud/* packages for GCP services (e.g., @google-cloud/storage for Cloud Storage instead of Drive API) - purpose-built clients for Google Cloud Platform services that may have better Workers support. Most Google APIs are REST-based and should work via fetch(), but the googleapis package's Node.js dependencies make it incompatible. Similar monolithic API client libraries include aws-sdk (AWS SDK v2, deprecated), azure-sdk (Azure services).
π‘ Alternative: @googleapis/* scoped packages (e.g., @googleapis/drive) - individual API packages that may work in Workers, or direct Google REST API calls using fetch()
Error: No such module "node:child_process".
Full GraphQL implementation: schema building (SDL or programmatic), query parsing, validation, and execution. Build complete GraphQL APIs on Workers.
import { graphql, buildSchema, parse, validate, GraphQLSchema, GraphQLObjectType, GraphQLString } from 'graphql';
export default {
async fetch(request) {
// SDL-based schema
const schema = buildSchema(`
type Query {
hello: String
user(id: Int!): User
}
type User { id: Int, name: String }
`);
const root = {
hello: () => 'Hello from Workers!',
user: ({ id }) => ({ id, name: 'User ' + id })
};
const result = await graphql({
schema,
source: '{ hello user(id: 1) { name } }',
rootValue: root
});
return Response.json(result);
}
};
GraphQL query parser for template literals
import gql from 'graphql-tag';
// Usage:
const query = gql`
query GetUser($id: ID!) {
user(id: $id) {
name
email
}
}
`;
return { success: query.kind === 'Document' && query.definitions.length > 0, result: { kind: query.kind, definitions: query.definitions.length } };
GraphQL schema building utilities - makeExecutableSchema, mergeSchemas, schema stitching
import { makeExecutableSchema } from 'graphql-tools';
// Usage:
// Create a simple GraphQL schema
const typeDefs = `
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => 'Hello from Workers!'
}
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
return {
success: schema != null && schema.getQueryType()?.name === 'Query',
result: { hasSchema: true, queryType: schema.getQueryType()?.name }
};
Parse YAML/JSON front matter from markdown strings. Supports custom delimiters, stringify for generating front matter, and excerpts. TOML requires additional engine config.
import matter from 'gray-matter';
export default {
async fetch(request) {
// Parse YAML front matter
const markdown = `---
title: My Post
date: 2024-01-15
tags: [js, workers]
---
# Content Here`;
const { data, content } = matter(markdown);
// JSON front matter
const json = `---json
{"title": "JSON"}
---
Content`;
const jsonParsed = matter(json);
// Stringify back to front matter
const output = matter.stringify('New content', { title: 'Generated' });
return Response.json({ yaml: data, json: jsonParsed.data, output });
}
};
DEPRECATED native module (C++ bindings via node-gyp) - official gRPC Node.js library that requires native compilation. Error 'spawnSync /bin/sh ETIMEDOUT' confirms it tries to compile C++ code during installation. The package provides gRPC client/server implementations with protocol buffer support, service definitions, client stubs, server implementations, streaming (unary, client streaming, server streaming, bidirectional), authentication (SSL/TLS, OAuth2, custom), metadata handling, and interceptors. Used for microservices communication with strongly-typed RPC calls, high-performance inter-service communication, polyglot systems (cross-language RPC), streaming data pipelines, and service mesh architectures. Native modules with C++ bindings cannot run in Workers' serverless JavaScript environment - no compilation/linking at runtime, no access to native code. The grpc team officially recommends using @grpc/grpc-js instead - a pure JavaScript implementation that provides the same gRPC functionality without native dependencies. @grpc/grpc-js offers: (1) Pure JavaScript - no native compilation required, (2) Drop-in replacement - same API as native grpc, (3) Active maintenance - regularly updated with latest gRPC features, (4) Better compatibility - works in more environments including Workers. Similar RPC libraries include @grpc/proto-loader (proto file loading), grpc-web (@grpc/grpc-web for browser gRPC), connect-node (modern RPC with gRPC support).
π‘ Alternative: @grpc/grpc-js (official pure JavaScript implementation, drop-in replacement recommended by gRPC team)
Node.js HTTP server framework - Workers uses fetch() handlers
π‘ Alternative: hono, itty-router
import hashSum from 'hash-sum';
// Usage:
const hash = hashSum({ foo: 'bar', nested: { value: 123 } });
return { success: typeof hash === 'string' && hash.length > 0, result: hash };
Pure JavaScript hash functions (SHA256, SHA512, RIPEMD160). Works on Workers.
import { sha256, sha512 } from 'hash.js';
const hash = sha256().update('hello world').digest('hex');
return { success: hash.length === 64, hash };
HTML entity encoder/decoder. Encode/decode HTML entities in strings.
import he from 'he';
// Usage:
const encoded = he.encode('<script>alert("xss")</script>');
const decoded = he.decode('<div>Hello</div>');
return { success: decoded === '<div>Hello</div>', result: { encoded, decoded } };
Express middleware for setting security HTTP headers (CSP, HSTS, X-Frame-Options, etc). Works with Express via httpServerHandler.
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import helmet from 'helmet';
const app = express();
app.use(helmet());
app.get('/test', (req, res) => {
res.json({ secure: true });
});
app.listen(3000);
export default httpServerHandler({ port: 3000 });
import H from 'highland';
// Usage:
const result: number[] = [];
H([1, 2, 3, 4])
.map((x: number) => x * 2)
.each((x: number) => result.push(x));
return { success: result.join(',') === '2,4,6,8', result };
Syntax highlighting library
import hljs from 'highlight.js';
// Usage:
const result = hljs.highlight('const x = 5;', { language: 'javascript' });
return { success: result.value.includes('const'), result: { highlighted: result.value.substring(0, 50) } };
Native C++ Redis client
π‘ Alternative: ioredis
Error: Command failed: npm install npm warn deprecated rollup-plugin-inject@3.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. npm warn deprecated sourcema
History/routing library for SPAs
import { createMemoryHistory } from 'history';
// Usage:
const history = createMemoryHistory();
history.push('/test');
return { success: history.location.pathname === '/test', result: { pathname: history.location.pathname } };
Deprecated - use @hapi/hoek instead
π‘ Alternative: @hapi/hoek
Error: Failed to load url @hapi/hoek (resolved id: @hapi/hoek) in /Users/steve/works-on-workers/packages/test-harness/sandbox/hoek/src/index.ts. Does the file exist?
import Hogan from 'hogan.js';
// Usage:
const template = Hogan.compile('Hello {{name}}!');
const result = template.render({ name: 'World' });
return { success: result === 'Hello World!', result };
Copies non-React static properties
import hoistStatics from 'hoist-non-react-statics';
// Usage:
function Target() {}
function Source() {}
Source.foo = 'bar';
hoistStatics(Target, Source);
return { success: (Target as any).foo === 'bar', result: { foo: (Target as any).foo } };
Ultra-fast web framework built specifically for edge/Workers. Includes middleware (cors, logger, jwt, validator), routing, context helpers. Recommended for building APIs on Workers.
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { prettyJSON } from 'hono/pretty-json';
const app = new Hono();
app.use('*', cors());
app.use('*', prettyJSON());
app.get('/', (c) => c.json({ message: 'Hello!' }));
app.get('/users/:id', (c) => c.json({ userId: c.req.param('id') }));
app.post('/data', async (c) => c.json({ body: await c.req.json() }));
export default app;
import { encode, decode } from 'html-entities';
// Usage:
const encoded = encode('<div>Hello & goodbye</div>');
const decoded = decode('<div>Hello & goodbye</div>');
return { success: encoded === '<div>Hello & goodbye</div>' && decoded === '<div>Hello & goodbye</div>', result: { encoded, decoded } };
Fast streaming HTML/XML parser with DOM utilities. Use with dom-serializer for HTML output. Good alternative to cheerio for lower-level parsing.
import { parseDocument, DomUtils } from 'htmlparser2';
import render from 'dom-serializer';
export default {
async fetch(request) {
const response = await fetch('https://example.com');
const html = await response.text();
const dom = parseDocument(html);
// Find elements
const h1 = DomUtils.findOne(el => el.name === 'h1', dom.children, true);
const title = h1 ? DomUtils.textContent(h1) : null;
const links = DomUtils.findAll(el => el.name === 'a', dom.children, true);
// Serialize back to HTML
const serialized = render(dom);
return Response.json({ title, linkCount: links.length });
}
};
Built-in Node.js module, polyfilled in Workers
Create HTTP errors with proper status codes. Useful for API error responses.
import createError from 'http-errors';
// Usage:
const err = createError(404, 'User not found');
return { success: err.status === 404, result: { status: err.status, message: err.message } };
HTTP proxy server - use with httpServerHandler from cloudflare:node
import httpProxy from 'http-proxy';
// Usage:
// http-proxy creates HTTP proxy servers - requires node:http server APIs
const proxy = httpProxy.createProxyServer();
return { success: true, result: 'HTTP proxy created' };
HTTP proxy middleware for Express/Connect. Works with httpServerHandler but the actual proxying may have issues with some request types. Simple proxy forwarding works. For complex proxy needs, consider using native fetch() directly.
π‘ Alternative: Use native fetch() for proxying requests
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import { createProxyMiddleware } from 'http-proxy-middleware';
const app = express();
// Note: Basic proxying works but may have edge cases
const apiProxy = createProxyMiddleware({
target: 'https://api.example.com',
changeOrigin: true
});
app.use('/api', apiProxy);
app.get('/', (req, res) => res.json({ message: 'Proxy ready' }));
app.listen(3000);
export default httpServerHandler({ port: 3000 });
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
// Usage:
const ok = StatusCodes.OK;
const notFound = StatusCodes.NOT_FOUND;
const phrase = getReasonPhrase(200);
return { success: ok === 200 && notFound === 404 && phrase === 'OK', result: { ok, notFound, phrase } };
Built-in Node.js module, polyfilled in Workers
HTTP(S) proxy agent. Creates agent but Workers fetch() does not use Node.js agents - limited practical use.
import { HttpsProxyAgent } from 'https-proxy-agent';
// Usage:
const agent = new HttpsProxyAgent('http://proxy.example.com:8080');
return { success: agent.proxy.hostname === 'proxy.example.com', result: { host: agent.proxy.hostname, port: agent.proxy.port } };
Incompatible node:url APIs (url.parse)
π‘ Alternative: fetch or ky
Error: url.parse is not a function
Internationalization framework with interpolation, pluralization, language detection, fallbacks. Works on Workers for multi-language APIs.
import i18next from 'i18next';
export default {
async fetch(request) {
await i18next.init({
lng: 'en',
fallbackLng: 'en',
resources: {
en: { translation: { greeting: 'Hello, {{name}}!', welcome: 'Welcome' } },
es: { translation: { greeting: 'Β‘Hola, {{name}}!', welcome: 'Bienvenido' } }
}
});
const en = i18next.t('greeting', { name: 'World' });
await i18next.changeLanguage('es');
const es = i18next.t('greeting', { name: 'Mundo' });
return Response.json({ en, es });
}
};
import iconv from 'iconv-lite';
// Usage:
const encoded = iconv.encode('Hello', 'utf8');
const decoded = iconv.decode(encoded, 'utf8');
return { success: decoded === 'Hello', result: decoded };
import identityObj from 'identity-obj-proxy';
// Usage:
// Identity proxy returns property names as values (for testing)
const result = identityObj.foo === 'foo' && identityObj.bar === 'bar';
return { success: result, result: { foo: identityObj.foo, bar: identityObj.bar } };
Get image dimensions from buffer or file
import sizeOf from 'image-size';
// Usage:
// Create a simple 1x1 PNG (base64 encoded)
const pngData = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==', 'base64');
const dimensions = sizeOf(pngData);
return { success: dimensions.width === 1 && dimensions.height === 1 && dimensions.type === 'png', result: dimensions };
Immutable state updates with mutable syntax. Supports nested objects, arrays, Maps, Sets. Great for state management in Workers.
import { produce, enableMapSet } from 'immer';
enableMapSet();
export default {
async fetch(request) {
const state = {
users: [{ id: 1, name: 'Alice' }],
settings: { theme: 'light' }
};
const nextState = produce(state, draft => {
draft.users.push({ id: 2, name: 'Bob' });
draft.settings.theme = 'dark';
});
// Curried producer
const addUser = produce((draft, user) => { draft.users.push(user); });
const withNewUser = addUser(nextState, { id: 3, name: 'Charlie' });
return Response.json({ original: state, updated: withNewUser });
}
};
Immutable state updates for React and other frameworks
import update from 'immutability-helper';
// Usage:
const state = { name: 'Alice', age: 30 };
const newState = update(state, { age: { $set: 31 } });
return { success: newState.age === 31 && state.age === 30, result: newState };
import { Map } from 'immutable';
// Usage:
const map = Map({ a: 1, b: 2 });
const map2 = map.set('c', 3);
return { success: map2.get('c') === 3 && map2.size === 3, result: map2.toObject() };
import inflection from 'inflection';
// Usage:
const plural = inflection.pluralize('person');
const singular = inflection.singularize('people');
const camel = inflection.camelize('hello_world');
return { success: plural === 'people' && singular === 'person' && camel === 'HelloWorld', result: { plural, singular, camel } };
import inherits from 'inherits';
// Usage:
function Parent() { this.name = 'parent'; }
Parent.prototype.getName = function() { return this.name; };
function Child() { Parent.call(this); this.name = 'child'; }
inherits(Child, Parent);
const child = new Child();
return { success: child.getName() === 'child', result: child.getName() };
import ini from 'ini';
// Usage:
const obj = { section: { key: 'value', number: 42 } };
const str = ini.stringify(obj);
const parsed = ini.parse(str);
return { success: parsed.section.key === 'value', result: parsed };
Intl API is built into Workers runtime
import { IntlMessageFormat } from 'intl-messageformat';
// Usage:
const msg = new IntlMessageFormat('Hello {name}!', 'en-US');
const result = msg.format({ name: 'World' });
return { success: result === 'Hello World!', result };
import invariant from 'invariant';
// Usage:
let error;
try {
invariant(false, 'This is an error');
} catch (e) {
error = e.message;
}
return { success: error === 'This is an error', result: error };
IoC container with dependency injection
import { Container, injectable, inject } from 'inversify';
// Usage:
@injectable()
class Warrior {
constructor() {}
fight() { return 'fight!'; }
}
const container = new Container();
container.bind(Warrior).toSelf();
const warrior = container.get(Warrior);
return { success: warrior.fight() === 'fight!', result: warrior.fight() };
Redis client for Node.js. Use Cloudflare Workers KV for key-value storage or @upstash/redis for Redis over HTTP.
π‘ Alternative: @upstash/redis
IP address utilities - validation, parsing, subnet checking, IPv4/IPv6 conversion.
import ip from 'ip';
// Usage:
const isPrivate = ip.isPrivate('192.168.1.1');
const isPublic = ip.isPublic('8.8.8.8');
return { success: isPrivate && isPublic, result: { isPrivate, isPublic } };
import isNumber from 'is-number';
// Usage:
const results = [isNumber(123), isNumber('123'), isNumber('abc'), isNumber(null)];
return { success: results[0] && results[1] && !results[2] && !results[3], result: results };
import { isPlainObject } from 'is-plain-object';
// Usage:
const r1 = isPlainObject({});
const r2 = isPlainObject([]);
return { success: r1 && !r2, result: { object: r1, array: r2 } };
import isPromise from 'is-promise';
// Usage:
const a = isPromise(Promise.resolve(123));
const b = isPromise({ then: () => {} });
const c = isPromise(123);
return { success: a === true && b === true && c === false, result: { a, b, c } };
Validate if a string is a valid URL
import isUrl from 'is-url';
// Usage:
const results = [
isUrl('https://example.com'),
isUrl('http://example.com/path'),
isUrl('not a url'),
isUrl('example.com')
];
return { success: results[0] && results[1] && !results[2] && !results[3], result: results };
import isObject from 'isobject';
// Usage:
const results = [isObject({}), isObject([]), isObject(null), isObject('test')];
return { success: results[0] && !results[1] && !results[2] && !results[3], result: results };
import 'isomorphic-fetch';
// Usage:
// isomorphic-fetch polyfills fetch globally
const result = typeof fetch === 'function';
return { success: result, result: 'fetch is available' };
Tiny (~1KB) router built for Workers. v5 uses AutoRouter for automatic JSON responses. Supports params, query strings, middleware. Simpler than Hono but less features.
import { AutoRouter } from 'itty-router';
const router = AutoRouter();
// Routes return objects - auto-converted to JSON
router.get('/', () => ({ message: 'Hello!' }));
router.get('/users/:id', ({ id }) => ({ userId: id }));
router.get('/search', (req) => {
const url = new URL(req.url);
return { query: url.searchParams.get('q') };
});
router.post('/data', async (req) => ({ body: await req.json() }));
export default router;
JavaScript image manipulation. Pure JS image processing - resize, crop, rotate, filters, etc.
import { Jimp } from 'jimp';
// Usage:
const image = new Jimp({ width: 100, height: 100, color: 0xff0000ff });
return { success: true, result: { width: image.width, height: image.height } };
Powerful schema validation with nested objects, arrays, conditionals, custom messages. Works on Workers unlike ajv (which uses new Function).
import Joi from 'joi';
export default {
async fetch(request) {
const userSchema = Joi.object({
username: Joi.string().alphanum().min(3).max(30).required(),
email: Joi.string().email().required(),
age: Joi.number().integer().min(0).max(120),
role: Joi.string().valid('admin', 'user').default('user')
});
const body = await request.json();
const { error, value } = userSchema.validate(body, { abortEarly: false });
if (error) {
return Response.json({ errors: error.details.map(d => d.message) }, { status: 400 });
}
return Response.json({ valid: true, data: value });
}
};
Recommended JWT library for Workers. Supports JWT signing/verification (HS256, RS256, ES256), JWE encryption, JWK key management. Uses Web Crypto API - perfect for edge.
import * as jose from 'jose';
export default {
async fetch(request) {
// Sign JWT with HS256
const secret = new TextEncoder().encode('my-secret-32-chars-minimum-key!');
const jwt = await new jose.SignJWT({ sub: 'user123', role: 'admin' })
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('2h')
.sign(secret);
// Verify JWT
const { payload } = await jose.jwtVerify(jwt, secret);
// RSA key pair
const { publicKey, privateKey } = await jose.generateKeyPair('RS256');
// Encrypted JWT (JWE)
const key = await jose.generateSecret('A256GCM');
const jwe = await new jose.EncryptJWT({ secret: 'data' })
.setProtectedHeader({ alg: 'dir', enc: 'A256GCM' })
.encrypt(key);
return Response.json({ jwt, payload });
}
};
import { Base64 } from 'js-base64';
// Usage:
const encoded = Base64.encode('hello');
const decoded = Base64.decode(encoded);
return { success: decoded === 'hello', result: { encoded, decoded } };
import beautify from 'js-beautify';
// Usage:
const result = beautify('var x=1;', { indent_size: 2 });
return { success: result.includes('var x'), result };
Browser cookie library - requires document.cookie. In Workers, parse Cookie header manually or use a server-side cookie library.
import Cookies from 'js-cookie';
// Usage: js-cookie needs document.cookie (browser only)
// In Workers, parse cookies manually from request headers
const cookieHeader = request.headers.get('Cookie') || '';
return { success: true, result: { note: 'Use request.headers.get("Cookie") in Workers' } };
import sha256 from 'js-sha256';
// Usage:
const result = sha256('hello');
return { success: result.length === 64, result };
import yaml from 'js-yaml';
// Usage:
const obj = yaml.load('name: Alice\nage: 30');
return { success: true, result: obj };
import stringify from 'json-stable-stringify';
// Usage:
const result = stringify({ b: 2, a: 1 });
return { success: result === '{"a":1,"b":2}', result };
import stringify from 'json-stringify-safe';
// Usage:
const obj: any = { a: 1 };
obj.circular = obj;
const result = stringify(obj);
return { success: result.includes('"a":1'), result };
import JSON5 from 'json5';
// Usage:
const obj = JSON5.parse('{ key: "value", /* comment */ }');
return { success: obj.key === 'value', result: obj };
Works with Workers node:fs support. Can read/write JSON files to /tmp (ephemeral, per-request) or read from /bundle (bundled files, read-only). Not for persistent storage - use KV, R2, or D1 for that.
Error: no such file or directory
import jsonfile from 'jsonfile';
import { mkdirSync } from 'node:fs';
export default {
async fetch(request) {
// Write JSON to /tmp (ephemeral, per-request)
mkdirSync('/tmp/data', { recursive: true });
const data = { name: 'test', timestamp: Date.now() };
jsonfile.writeFileSync('/tmp/data/config.json', data, { spaces: 2 });
// Read it back
const result = jsonfile.readFileSync('/tmp/data/config.json');
return Response.json({ written: data, readBack: result });
}
};
import { Validator } from 'jsonschema';
// Usage:
const v = new Validator();
const result = v.validate({ name: 'test' }, { type: 'object', properties: { name: { type: 'string' } } });
return { success: result.valid, result: result.valid };
Streaming JSON parser
import JSONStream from 'JSONStream';
// Usage:
const stream = JSONStream.parse('*');
return { success: stream !== undefined && typeof stream.pipe === 'function', result: 'Stream created' };
import jwt from 'jsonwebtoken';
// Usage:
const token = jwt.sign({ sub: '123' }, 'secret');
const decoded = jwt.verify(token, 'secret');
return { success: decoded.sub === '123', result: decoded };
Create, read, and edit ZIP files in JavaScript
import JSZip from 'jszip';
// Usage:
const zip = new JSZip();
zip.file('hello.txt', 'Hello World!');
const content = await zip.generateAsync({ type: 'blob' });
return { success: content.size > 0, result: { size: content.size } };
import { jwtDecode } from 'jwt-decode';
// Usage:
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
const decoded = jwtDecode(token);
return { success: decoded.sub === '1234567890' && decoded.name === 'John Doe', result: decoded };
import kindOf from 'kind-of';
// Usage:
const result = [kindOf('test'), kindOf(123), kindOf([]), kindOf({})];
return { success: result.join(',') === 'string,number,array,object', result };
SQL query builder - use D1 or Hyperdrive
π‘ Alternative: @cloudflare/d1
Error: Command failed: npm install npm warn deprecated rollup-plugin-inject@3.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. npm warn deprecated sourcema
Node.js web framework. Works on Workers with httpServerHandler from cloudflare:node. Requires nodejs_compat flag.
π‘ Alternative: hono, itty-router
Error: Unexpected token ':'
import { httpServerHandler } from 'cloudflare:node';
import Koa from 'koa';
const app = new Koa();
app.use(async (ctx) => {
ctx.body = { message: 'Koa on Workers!' };
});
app.listen(3000);
export default httpServerHandler({ port: 3000 });
Koa body parsing middleware
π‘ Alternative: hono, itty-router
Error: Package koa-body needs manual test configuration - do not use generic Object.keys() test
Koa body parsing middleware
π‘ Alternative: hono, itty-router
Error: Command failed: npm install npm warn deprecated rollup-plugin-inject@3.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. npm warn deprecated sourcema
Koa middleware composition
π‘ Alternative: hono, itty-router
Error: Package koa-compose needs manual test configuration - do not use generic Object.keys() test
Koa logging middleware
π‘ Alternative: hono, itty-router
Error: Package koa-logger needs manual test configuration - do not use generic Object.keys() test
Koa routing middleware
π‘ Alternative: hono, itty-router
Error: Unexpected token ':'
Koa static file middleware
π‘ Alternative: hono, itty-router
Error: Unexpected token ':'
Tiny HTTP client based on fetch. Excellent for Workers - small bundle, modern API.
import ky from 'ky';
const data = await ky.get('https://api.example.com/data').json();
const posted = await ky.post('https://api.example.com/items', { json: { name: 'test' } }).json();
return { success: true, data };
Type-safe SQL query builder - use with D1 database
import { Kysely, sql } from 'kysely';
// Usage:
return { success: typeof Kysely === 'function' && typeof sql === 'function', result: 'Kysely exports available' };
LevelDB database abstraction
π‘ Alternative: @cloudflare/d1, @upstash/redis
Error: Package level needs manual test configuration - do not use generic Object.keys() test
LevelDB backend
π‘ Alternative: @cloudflare/d1, @upstash/redis
Error: Package leveldown needs manual test configuration - do not use generic Object.keys() test
LevelDB wrapper
π‘ Alternative: @cloudflare/d1, @upstash/redis
Error: Package levelup needs manual test configuration - do not use generic Object.keys() test
Liquid template engine (Shopify templating). Use liquidjs package: import { Liquid } from "liquidjs"
import { Liquid } from 'liquidjs';
// Usage:
const engine = new Liquid();
const result = await engine.parseAndRender('Hello {{ name }}!', { name: 'World' });
return { success: result === 'Hello World!', result };
import _ from 'lodash';
// Usage:
const result = _.chunk(['a', 'b', 'c', 'd'], 2);
return { success: true, result };
import { chunk } from 'lodash-es';
// Usage:
const result = chunk(['a', 'b', 'c', 'd'], 2);
return { success: true, result };
import assign from 'lodash.assign';
// Usage:
const result = assign({}, { a: 1 }, { b: 2 });
return { success: result.a === 1 && result.b === 2, result };
import camelCase from 'lodash.camelcase';
// Usage:
const result = camelCase('foo-bar');
return { success: result === 'fooBar', result };
import cloneDeep from 'lodash.clonedeep';
// Usage:
const obj = { a: { b: 1 } };
const clone = cloneDeep(obj);
clone.a.b = 2;
return { success: obj.a.b === 1 && clone.a.b === 2, result: { original: obj, clone } };
Debounce function from lodash. Works in Workers for rate-limiting function calls.
import debounce from 'lodash.debounce';
// Usage:
let count = 0;
const fn = debounce(() => { count++; }, 50);
fn(); fn(); fn();
await new Promise(r => setTimeout(r, 100));
return { success: count === 1, result: { count } };
import defaults from 'lodash.defaults';
// Usage:
const result = defaults({ a: 1 }, { a: 2, b: 3 });
return { success: result.a === 1 && result.b === 3, result };
import flatten from 'lodash.flatten';
// Usage:
const result = flatten([[1, 2], [3, 4]]);
return { success: result.join(',') === '1,2,3,4', result };
import forEach from 'lodash.foreach';
// Usage:
const result: number[] = [];
forEach([1, 2, 3], (n) => result.push(n * 2));
return { success: result.join(',') === '2,4,6', result };
import get from 'lodash.get';
// Usage:
const obj = { a: { b: { c: 123 } } };
const result = get(obj, 'a.b.c');
const missing = get(obj, 'x.y.z', 'default');
return { success: result === 123 && missing === 'default', result: { result, missing } };
import isEmpty from 'lodash.isempty';
// Usage:
const result = [isEmpty({}), isEmpty([]), isEmpty(''), isEmpty({ a: 1 })];
return { success: result[0] && result[1] && result[2] && !result[3], result };
import isEqual from 'lodash.isequal';
// Usage:
const result1 = isEqual({ a: 1 }, { a: 1 });
const result2 = isEqual({ a: 1 }, { a: 2 });
return { success: result1 && !result2, result: { result1, result2 } };
import isFunction from 'lodash.isfunction';
// Usage:
const result = [isFunction(() => {}), isFunction({}), isFunction(null)];
return { success: result[0] && !result[1] && !result[2], result };
import isPlainObject from 'lodash.isplainobject';
// Usage:
const result = [isPlainObject({}), isPlainObject([]), isPlainObject(null)];
return { success: result[0] && !result[1] && !result[2], result };
import isString from 'lodash.isstring';
// Usage:
const result = [isString('hello'), isString(123), isString(null)];
return { success: result[0] && !result[1] && !result[2], result };
import map from 'lodash.map';
// Usage:
const result = map([1, 2, 3], n => n * 2);
return { success: result.join(',') === '2,4,6', result };
import merge from 'lodash.merge';
// Usage:
const result = merge({ a: 1, b: { c: 2 } }, { b: { d: 3 } });
return { success: result.a === 1 && result.b.c === 2 && result.b.d === 3, result };
import omit from 'lodash.omit';
// Usage:
const result = omit({ a: 1, b: 2, c: 3 }, ['a', 'c']);
return { success: result.b === 2 && !result.a, result };
import pick from 'lodash.pick';
// Usage:
const result = pick({ a: 1, b: 2, c: 3 }, ['a', 'c']);
return { success: result.a === 1 && result.c === 3 && !result.b, result };
import set from 'lodash.set';
// Usage:
const obj = {};
set(obj, 'a.b.c', 123);
return { success: obj.a?.b?.c === 123, result: obj };
import throttle from 'lodash.throttle';
// Usage:
const fn = throttle(() => 'throttled', 100);
const result = fn();
return { success: result === 'throttled', result };
import uniq from 'lodash.uniq';
// Usage:
const result = uniq([1, 2, 2, 3, 1, 4]);
return { success: result.join(',') === '1,2,3,4', result };
import logSymbols from 'log-symbols';
// Usage:
const result = {
success: typeof logSymbols.success === 'string',
error: typeof logSymbols.error === 'string',
warning: typeof logSymbols.warning === 'string',
info: typeof logSymbols.info === 'string',
};
return { success: result.success && result.error && result.warning && result.info, result };
Requires node:os which is not supported
π‘ Alternative: console or pino
Error: No such module "node:os".
import log from 'loglevel';
// Usage:
log.setLevel('info');
const level = log.getLevel();
log.info('test');
return { success: typeof level === 'number', result: { level } };
import Long from 'long';
// Usage:
const val = Long.fromNumber(123456789);
const result = val.toString();
return { success: result === '123456789', result };
JSON database - works with custom adapters
import { Low } from 'lowdb';
// Usage:
const db = new Low({ read: async () => ({ posts: [] }), write: async () => {} }, { posts: [] });
await db.read();
return { success: Array.isArray(db.data.posts), result: db.data };
import { LRUCache } from 'lru-cache';
// Usage:
const cache = new LRUCache({ max: 100 });
cache.set('key', 'value');
const result = cache.get('key');
return { success: result === 'value', result };
import { DateTime } from 'luxon';
// Usage:
const dt = DateTime.fromISO('2026-01-08');
const formatted = dt.toFormat('yyyy-MM-dd');
return { success: formatted === '2026-01-08', result: formatted };
import LZString from 'lz-string';
// Usage:
const compressed = LZString.compress('hello world');
const decompressed = LZString.decompress(compressed);
return { success: decompressed === 'hello world', result: { compressed, decompressed } };
Stream mapping utility for transforming stream data
import mapStream from 'map-stream';
// Usage:
const stream = mapStream((data, callback) => {
callback(null, data * 2);
});
return { success: typeof stream === 'object', result: 'stream-utility' };
Markdown to HTML converter
import { markdown } from 'markdown';
// Usage:
const result = markdown.toHTML('# Hello');
return { success: result.includes('<h1>'), result };
Markdown parser and renderer
import MarkdownIt from 'markdown-it';
// Usage:
const md = new MarkdownIt();
const result = md.render('# Hello World');
return { success: result.includes('<h1>') && result.includes('Hello World'), result };
Fast markdown parser and compiler
import { marked } from 'marked';
// Usage:
const result = marked('# Hello **World**');
return { success: result.includes('<h1>') && result.includes('<strong>'), result };
Extensive math library - expressions, matrices, units, big numbers, complex numbers.
import { evaluate, sqrt, multiply, matrix } from 'mathjs';
// Usage:
const expr = evaluate('2 + 3 * 4');
const sqrtResult = sqrt(16);
const m = multiply(matrix([[1, 2], [3, 4]]), 2);
return { success: expr === 14, result: { expr, sqrt: sqrtResult, matrix: m.toArray() } };
MD5 hash function
import md5 from 'md5';
// Usage:
const result = md5('hello');
return { success: result === '5d41402abc4b2a76b9719d911017c592', result };
Parse and format media types (MIME types). Does not accept parameters in parse() - use content-type package for full parsing.
import typer from 'media-typer';
// Usage:
const parsed = typer.parse('text/html');
const formatted = typer.format({ type: 'application', subtype: 'json' });
return { success: parsed.type === 'text', result: { parsed, formatted } };
Memoization with single result cache
import memoizeOne from 'memoize-one';
// Usage:
let calls = 0;
const fn = memoizeOne((a, b) => { calls++; return a + b; });
fn(1, 2); fn(1, 2); fn(2, 3);
return { success: calls === 2, result: { calls } };
Function memoization with TTL, max cache size, and async support.
π‘ Alternative: memoize-one
import memoize from 'memoizee';
// Usage:
let callCount = 0;
const expensive = memoize((x) => { callCount++; return x * 2; });
expensive(5); expensive(5); expensive(10);
return { success: callCount === 2, result: { callCount } };
import merge from 'merge';
// Usage:
const result = merge({ a: 1 }, { b: 2 });
return { success: result.a === 1 && result.b === 2, result };
Utility for merging multiple readable streams into one. Works with Workers node:stream support.
import mergeStream from 'merge-stream';
import { Readable } from 'node:stream';
export default {
async fetch(request) {
// Create readable streams
const stream1 = Readable.from(['Hello ', 'from ', 'stream1! ']);
const stream2 = Readable.from(['And ', 'stream2 ', 'too!']);
// Merge them
const merged = mergeStream(stream1, stream2);
// Collect all data
const chunks = [];
for await (const chunk of merged) {
chunks.push(chunk);
}
return Response.json({ result: chunks.join('''') });
}
};
Express middleware - requires HTTP framework
import methodOverride from 'method-override';
// Usage:
const fn = methodOverride();
return { success: typeof fn === 'function', result: 'middleware function' };
HTTP method name constants
import methods from 'methods';
// Usage:
return { success: Array.isArray(methods) && methods.includes('get'), result: methods.slice(0, 5) };
import micromatch from 'micromatch';
// Usage:
const result = micromatch(['foo.js', 'bar.txt'], '*.js');
return { success: result.length === 1 && result[0] === 'foo.js', result };
MIME type lookup by file extension. Useful for setting Content-Type headers.
import mime from 'mime';
const type = mime.getType('file.json'); // 'application/json'
const ext = mime.getExtension('text/html'); // 'html'
return { success: type === 'application/json', type, ext };
ESM parsing issue with Workerd. Use 'mime' package instead which includes mime-db
π‘ Alternative: mime
MIME type lookup and extension detection. Works perfectly in Workers.
import mimeTypes from 'mime-types';
// Usage:
const type = mimeTypes.lookup('test.json');
const ext = mimeTypes.extension('application/json');
return { success: type === 'application/json', result: { type, ext } };
import { minimatch } from 'minimatch';
// Usage:
const result = minimatch('foo.js', '*.js');
return { success: result === true, result };
import minimist from 'minimist';
// Usage:
const args = minimist(['--foo', 'bar', '-n', '3']);
return { success: args.foo === 'bar' && args.n === 3, result: args };
import mitt from 'mitt';
// Usage:
const emitter = mitt();
let result = '';
emitter.on('test', (data) => { result = data; });
emitter.emit('test', 'hello');
return { success: result === 'hello', result };
import { observable, autorun } from 'mobx';
// Usage:
const state = observable({ count: 0 });
let result = 0;
autorun(() => { result = state.count; });
state.count = 5;
return { success: result === 5, result };
Mock data generator
import Mock from 'mockjs';
// Usage:
const result = Mock.mock({ 'number|1-100': 1 });
return { success: typeof result.number === 'number', result };
Consider using dayjs or date-fns for smaller bundle size
import moment from 'moment';
// Usage:
const date = moment('2026-01-08');
const formatted = date.format('YYYY-MM-DD');
return { success: formatted === '2026-01-08', result: formatted };
Moment.js with timezone support. Works in Workers for date/time manipulation with timezone awareness.
import moment from 'moment-timezone';
// Usage:
const la = moment.tz('2026-01-08 12:00', 'America/Los_Angeles');
const tokyo = la.clone().tz('Asia/Tokyo');
return { success: true, result: { la: la.format(), tokyo: tokyo.format() } };
MongoDB driver - use D1 or @upstash/redis instead
π‘ Alternative: @cloudflare/d1, @upstash/redis
Error: Maximum call stack size exceeded
MongoDB ORM - use D1 with Drizzle ORM instead
π‘ Alternative: @cloudflare/d1, drizzle-orm
Error: Maximum call stack size exceeded
MQTT client. Works with WebSocket transport (wss://). TCP connections not supported in Workers.
import mqtt from 'mqtt';
// Usage: MQTT needs WebSocket URL in Workers (not TCP)
const clientId = 'worker-' + Math.random().toString(16).slice(2, 8);
// const client = mqtt.connect('wss://broker.example.com:8884');
return { success: true, result: { clientId, note: 'Use wss:// WebSocket URL, not tcp://' } };
Parse/format milliseconds
import ms from 'ms';
// Usage:
const result = ms('2 days');
const str = ms(60000);
return { success: result === 172800000 && str === '1m', result: { parsed: result, formatted: str } };
MessagePack serialization
import msgpack from 'msgpack-lite';
// Usage:
const data = { hello: 'world', num: 42 };
const encoded = msgpack.encode(data);
const decoded = msgpack.decode(encoded);
return { success: decoded.hello === 'world' && decoded.num === 42, result: decoded };
Microsoft SQL Server driver - use D1 instead
π‘ Alternative: @cloudflare/d1
Error: Package mssql needs manual test configuration - do not use generic Object.keys() test
Express middleware for handling multipart/form-data (file uploads). Works with memoryStorage - diskStorage not available in Workers.
Error: Unexpected token ':'
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import multer from 'multer';
const app = express();
const upload = multer({ storage: multer.memoryStorage() });
app.post('/upload', upload.single('file'), (req, res) => {
res.json({ filename: req.file.originalname, size: req.file.size });
});
app.listen(3000);
export default httpServerHandler({ port: 3000 });
Match files against glob patterns
import multimatch from 'multimatch';
// Usage:
const result = multimatch(['foo.js', 'bar.css', 'baz.html'], ['*.js', '*.css']);
return { success: result.length === 2 && result.includes('foo.js'), result };
Logic-less template syntax
import Mustache from 'mustache';
// Usage:
const template = 'Hello {{name}}!';
const result = Mustache.render(template, { name: 'World' });
return { success: result === 'Hello World!', result };
MySQL client - use Cloudflare D1, @planetscale/database, or mysql2 with TCP socket support
π‘ Alternative: @planetscale/database or mysql2
import * as pkg from 'mysql';
// Usage:
const keys = Object.keys(pkg);
return { success: keys.length > 0, result: { exports: keys.slice(0, 5) } };
MySQL client requires TCP sockets
π‘ Alternative: D1 (SQLite on Cloudflare), @planetscale/database (HTTP-based MySQL)
import { nanoid } from 'nanoid';
// Usage:
const id = nanoid();
return { success: id.length === 21, result: id };
In-memory/file-based database
π‘ Alternative: D1 (SQLite), @upstash/redis, KV
import Negotiator from 'negotiator';
// Usage:
const negotiator = new Negotiator({ headers: { accept: 'text/html,application/json;q=0.9' } });
const types = negotiator.mediaTypes();
return { success: types.includes('text/html'), result: types };
In-memory caching
import NodeCache from 'node-cache';
// Usage:
const cache = new NodeCache();
cache.set('key', 'value', 10);
const result = cache.get('key');
return { success: result === 'value', result };
Emoji utilities - find, replace, parse emojis in text.
import * as emoji from 'node-emoji';
// Usage:
const result = emoji.emojify('I :heart: :coffee:!');
const hasEmoji = emoji.has(':heart:');
return { success: hasEmoji, result: { text: result, hasHeart: hasEmoji } };
Workers has native fetch() - no need for this package
π‘ Alternative: built-in: fetch
import fetch from 'node-fetch';
// Usage:
return { success: true, result: 'Use native fetch instead' };
Cryptography utilities
import forge from 'node-forge';
// Usage:
const md = forge.md.sha256.create();
md.update('test');
const result = md.digest().toHex();
return { success: result.length === 64, result };
Static file server for Node.js. While node:fs now works in Workers, node-static depends on Node.js stream and http internals that are not fully compatible. Use Workers Static Assets instead - it is the built-in, optimized solution.
π‘ Alternative: Workers Static Assets (https://developers.cloudflare.com/workers/static-assets/)
Error: ENOENT: no such file or directory
Deprecated package. Use uuid or crypto.randomUUID()
π‘ Alternative: uuid
Error: Disallowed operation called within global scope. Asynchronous I/O (ex: fetch() or connect()), setting a timeout, and generating random values are not allowed within global scope. To fix this error, pe
Object extend utility
import extend from 'node.extend';
// Usage:
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const result = extend(obj1, obj2);
return { success: result.a === 1 && result.b === 3 && result.c === 4, result };
Native Git bindings - C++ module
π‘ Alternative: @cloudflare/workers-github-api
Error: spawnSync /bin/sh ETIMEDOUT
Normalizes URLs by removing default ports, sorting query params, resolving paths, etc.
import normalizeUrl from 'normalize-url';
// Usage:
const url = normalizeUrl('https://example.com:443//foo/../bar?c=1&a=2');
return { success: url === 'https://example.com/bar?a=2&c=1', result: url };
Format and manipulate numbers (currency, percentages, etc.)
import numeral from 'numeral';
// Usage:
const formatted = numeral(1000).format('0,0');
const value = numeral('1,000').value();
return { success: formatted === '1,000' && value === 1000, result: { formatted, value } };
OAuth 1.0 client - use arctic (OAuth 2.0) or @cloudflare/access for Workers
π‘ Alternative: arctic or @cloudflare/access
Use native Object.assign() instead
import objectAssign from 'object-assign';
// Usage:
const result = objectAssign({}, { a: 1 }, { b: 2 }, { a: 3 });
return { success: result.a === 3 && result.b === 2, result };
Generate consistent hashes from JavaScript objects regardless of key order. Useful for caching and deduplication.
import hash from 'object-hash';
// Key order doesn't matter
const h1 = hash({ a: 1, b: 2 });
const h2 = hash({ b: 2, a: 1 });
return { success: h1 === h2, hash: h1 };
Access deep object properties using path strings
import objectPath from 'object-path';
// Usage:
const obj = { a: { b: { c: 1 } } };
const val = objectPath.get(obj, 'a.b.c');
objectPath.set(obj, 'a.b.d', 2);
return { success: val === 1 && obj.a.b.d === 2, result: { val, obj } };
import onFinished from 'on-finished';
// Usage:
const mockRes = {
finished: false,
headersSent: false,
on: function(event, cb) { if (event === 'finish') setTimeout(cb, 0); return this; },
once: function(event, cb) { return this.on(event, cb); },
removeListener: function() { return this; }
};
let called = false;
onFinished(mockRes, () => { called = true; });
return { success: true, result: 'onFinished called' };
import once from 'once';
// Usage:
let count = 0;
const fn = once(() => count++);
fn(); fn(); fn();
return { success: count === 1, result: count };
TypeScript type definitions for OpenAPI specifications
import type { OpenAPI, OpenAPIV3 } from 'openapi-types';
// Usage:
const schema: OpenAPIV3.SchemaObject = { type: 'string' };
return { success: schema.type === 'string', result: schema };
Node.js os module. Available via node:os with nodejs_compat. Returns limited info in Workers.
Error: Package os needs manual test configuration - do not use generic Object.keys() test
import os from 'node:os';
// Get system info
const info = {
platform: os.platform(),
arch: os.arch(),
tmpdir: os.tmpdir()
};
return { success: true, info };
Run promise-returning functions concurrently with optional concurrency limit
import pAll from 'p-all';
// Usage:
const tasks = [
() => Promise.resolve(1),
() => Promise.resolve(2),
() => Promise.resolve(3)
];
const result = await pAll(tasks, { concurrency: 2 });
return { success: result.length === 3 && result[0] === 1, result };
import pLimit from 'p-limit';
// Usage:
const limit = pLimit(2);
const results = await Promise.all([
limit(() => Promise.resolve(1)),
limit(() => Promise.resolve(2)),
]);
return { success: true, result: results };
Map over promises concurrently with optional concurrency limit
import pMap from 'p-map';
// Usage:
const input = [1, 2, 3];
const mapper = x => Promise.resolve(x * 2);
const result = await pMap(input, mapper, { concurrency: 2 });
return { success: result.length === 3 && result[0] === 2, result };
import PQueue from 'p-queue';
// Usage:
const queue = new PQueue({ concurrency: 1 });
const results = await Promise.all([
queue.add(() => Promise.resolve(1)),
queue.add(() => Promise.resolve(2)),
]);
return { success: true, result: results };
Retry failed promises with exponential backoff
import pRetry from 'p-retry';
// Usage:
let count = 0;
const run = async () => {
count++;
if (count < 3) throw new Error('fail');
return 'success';
};
const result = await pRetry(run, { retries: 5 });
return { success: result === 'success' && count === 3, result: { result, count } };
Throttle promise-returning/async functions. Limit concurrent executions over time.
import pThrottle from 'p-throttle';
// Usage:
const throttle = pThrottle({ limit: 2, interval: 1000 });
const throttled = throttle(async (x) => x * 2);
const result = await throttled(5);
return { success: result === 10, result: { value: result } };
import pako from 'pako';
// Usage:
const input = new TextEncoder().encode('Hello, World!');
const compressed = pako.deflate(input);
const decompressed = pako.inflate(compressed);
const output = new TextDecoder().decode(decompressed);
return { success: output === 'Hello, World!', result: output };
import Papa from 'papaparse';
// Usage:
const csv = 'name,age\nJohn,30\nJane,25';
const result = Papa.parse(csv, { header: true });
return { success: result.data.length === 2, result: result.data };
HTML5 parser
import { parse } from 'parse5';
// Usage:
const doc = parse('<html><body><h1>Test</h1></body></html>');
return { success: doc.nodeName === '#document', result: { nodeName: doc.nodeName } };
import parseurl from 'parseurl';
// Usage:
const req = { url: '/path?foo=bar' };
const parsed = parseurl(req);
return { success: parsed.pathname === '/path', result: parsed.pathname };
Authentication middleware for Express. Works with httpServerHandler and express-session.
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import session from 'express-session';
import passport from 'passport';
import { Strategy as LocalStrategy } from 'passport-local';
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(session({ secret: 'secret', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy((username, password, done) => {
if (username === 'admin' && password === 'pass') return done(null, { id: 1, username });
return done(null, false);
}));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => done(null, { id, username: 'admin' }));
app.post('/login', passport.authenticate('local'), (req, res) => res.json({ user: req.user }));
app.listen(3000);
export default httpServerHandler({ port: 3000 });
Username/password authentication strategy for Passport. Works with Express via httpServerHandler.
π‘ Alternative: @cloudflare/access
Error: spawn npm ENOENT
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import session from 'express-session';
import passport from 'passport';
import { Strategy as LocalStrategy } from 'passport-local';
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(session({ secret: 'secret', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy((username, password, done) => {
// Verify credentials against your user store
if (username === 'admin' && password === 'pass') {
return done(null, { id: 1, username });
}
return done(null, false, { message: 'Invalid credentials' });
}));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => done(null, { id }));
app.post('/login', passport.authenticate('local'), (req, res) => {
res.json({ success: true, user: req.user });
});
app.listen(3000);
export default httpServerHandler({ port: 3000 });
OAuth 1.0 authentication strategy for Passport. Works with Express via httpServerHandler.
π‘ Alternative: arctic / @cloudflare/access
Error: Package passport-oauth needs manual test configuration - do not use generic Object.keys() test
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import session from 'express-session';
import passport from 'passport';
import { OAuthStrategy } from 'passport-oauth';
const app = express();
app.use(session({ secret: 'secret', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new OAuthStrategy({
requestTokenURL: 'https://api.example.com/oauth/request_token',
accessTokenURL: 'https://api.example.com/oauth/access_token',
userAuthorizationURL: 'https://api.example.com/oauth/authorize',
consumerKey: process.env.OAUTH_CONSUMER_KEY,
consumerSecret: process.env.OAUTH_CONSUMER_SECRET,
callbackURL: 'https://myapp.com/auth/callback'
}, (token, tokenSecret, profile, done) => done(null, { token, profile })));
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));
app.get('/auth/provider', passport.authenticate('oauth'));
app.get('/auth/callback', passport.authenticate('oauth'), (req, res) => res.json({ user: req.user }));
app.listen(3000);
export default httpServerHandler({ port: 3000 });
OAuth 2.0 authentication strategy for Passport. Works with Express via httpServerHandler.
π‘ Alternative: arctic / @cloudflare/access
Error: Package passport-oauth2 needs manual test configuration - do not use generic Object.keys() test
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import session from 'express-session';
import passport from 'passport';
import OAuth2Strategy from 'passport-oauth2';
const app = express();
app.use(session({ secret: 'secret', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new OAuth2Strategy({
authorizationURL: 'https://github.com/login/oauth/authorize',
tokenURL: 'https://github.com/login/oauth/access_token',
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL: 'https://myapp.com/auth/callback'
}, (accessToken, refreshToken, profile, done) => done(null, { accessToken, profile })));
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));
app.get('/auth/github', passport.authenticate('oauth2'));
app.get('/auth/callback', passport.authenticate('oauth2'), (req, res) => res.json({ user: req.user }));
app.listen(3000);
export default httpServerHandler({ port: 3000 });
Base class for creating custom Passport authentication strategies. Works with Express via httpServerHandler.
π‘ Alternative: arctic / @cloudflare/access
Error: Package passport-strategy needs manual test configuration - do not use generic Object.keys() test
import { httpServerHandler } from 'cloudflare:node';
import express from 'express';
import passport from 'passport';
import Strategy from 'passport-strategy';
// Custom API key strategy
class ApiKeyStrategy extends Strategy {
constructor() { super(); this.name = 'apikey'; }
authenticate(req) {
const apiKey = req.headers['x-api-key'];
if (apiKey === 'valid-key') this.success({ id: 1, name: 'API User' });
else this.fail({ message: 'Invalid API key' }, 401);
}
}
const app = express();
app.use(passport.initialize());
passport.use(new ApiKeyStrategy());
app.get('/api/protected', passport.authenticate('apikey', { session: false }), (req, res) => {
res.json({ user: req.user });
});
app.listen(3000);
export default httpServerHandler({ port: 3000 });
Node.js path module (polyfilled in Workers)
import path from 'path';
// Usage:
const result = {
join: path.join('/foo', 'bar', 'baz.txt'),
dirname: path.dirname('/foo/bar/baz.txt'),
extname: path.extname('index.html')
};
return { success: result.join === '/foo/bar/baz.txt' && result.dirname === '/foo/bar' && result.extname === '.html', result };
Check if path is absolute
import pathIsAbsolute from 'path-is-absolute';
// Usage:
const abs = pathIsAbsolute('/foo/bar');
const rel = pathIsAbsolute('foo/bar');
return { success: abs === true && rel === false, result: { abs, rel } };
Path pattern matching - useful for routing in Workers
import { match } from 'path-to-regexp';
// Usage:
const matchFn = match('/user/:id');
const result = matchFn('/user/123');
return { success: result !== false && result.params.id === '123', result };
PDF creation and manipulation - works in Workers!
import { PDFDocument } from 'pdf-lib';
// Usage:
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([600, 400]);
page.drawText('Hello Workers!', { x: 50, y: 350, size: 30 });
const pdfBytes = await pdfDoc.save();
return { success: pdfBytes.length > 0, result: { size: pdfBytes.length } };
Use @cloudflare/stream or pdf-lib for PDF generation
π‘ Alternative: pdf-lib
Error: Unexpected token ':'
PostgreSQL client for Node.js. Use @neondatabase/serverless or Hyperdrive for Workers
import pkg from 'pg';
// Usage:
const { Client } = pkg;
const client = new Client({ connectionString: 'postgresql://test' });
return { success: typeof client.connect === 'function', result: { hasClient: true } };
Fast glob matcher used by many tools
import picomatch from 'picomatch';
// Usage:
const isMatch = picomatch('*.js');
const result = { match: isMatch('test.js'), noMatch: !isMatch('test.css') };
return { success: result.match && result.noMatch, result };
Promisify callback-based functions
import pify from 'pify';
// Usage:
const fn = (arg: string, callback: (err: null, result: string) => void) => {
callback(null, arg.toUpperCase());
};
const promisified = pify(fn);
const result = await promisified('hello');
return { success: result === 'HELLO', result };
import pino from 'pino';
// Usage:
const logger = pino({ level: 'info' });
logger.info({ test: true }, 'Hello from pino');
return { success: true, result: 'logged' };
Parse/build Apple plist files
import plist from 'plist';
// Usage:
const obj = { name: 'test', version: 1 };
const xml = plist.build(obj);
const parsed = plist.parse(xml);
return { success: parsed.name === 'test', result: parsed };
Pluralization/singularization utility
import pluralize from 'pluralize';
// Usage:
const result1 = pluralize('person'); // 'people'
const result2 = pluralize('person', 1); // 'person'
const result3 = pluralize('person', 5); // 'people'
return {
success: result1 === 'people' && result2 === 'person' && result3 === 'people',
result: { result1, result2, result3 }
};
PNG encoder/decoder
import { PNG } from 'pngjs';
// Usage:
const png = new PNG({ width: 10, height: 10 });
return { success: png.width === 10, result: { width: png.width, height: png.height } };
CSS-in-JS utility library
import { darken, lighten } from 'polished';
// Usage:
const darker = darken(0.1, '#CCCCCC');
const lighter = lighten(0.1, '#333333');
return { success: typeof darker === 'string' && typeof lighter === 'string', result: { darker, lighter } };
Lightweight React alternative, SSR works great
import { h } from 'preact';
import renderToString from 'preact-render-to-string';
// Usage:
const element = h('div', null, 'Hello, World!');
const html = renderToString(element);
return { success: html.includes('Hello, World!'), result: html };
Convert bytes to human readable string
import prettyBytes from 'pretty-bytes';
// Usage:
const result = prettyBytes(1337);
return { success: result === '1.34 kB', result };
Pretty print error stack traces with colors and formatting.
import PrettyError from 'pretty-error';
// Usage:
const pe = new PrettyError();
const err = new Error('Something went wrong');
const rendered = pe.render(err);
return { success: rendered.includes('Something went wrong'), result: { length: rendered.length } };
Format JSON with colors and indentation for readable output.
π‘ Alternative: JSON.stringify(obj, null, 2)
import prettyjson from 'prettyjson';
// Usage:
const data = { name: 'test', count: 42 };
const pretty = prettyjson.render(data);
return { success: pretty.includes('name'), result: { length: pretty.length } };
ES6 Promise polyfill. Workers has native Promise support built-in.
π‘ Alternative: native Promise
Promise polyfill - Promises are native in Workers
React PropTypes - runtime type checking for React components
import PropTypes from 'prop-types';
// Usage:
const stringType = PropTypes.string.isRequired;
const numberType = PropTypes.number;
const objectShape = PropTypes.shape({
name: PropTypes.string,
age: PropTypes.number
});
return {
success: typeof stringType === 'function' && typeof numberType === 'function',
result: { hasString: !!stringType, hasNumber: !!numberType, hasShape: !!objectShape }
};
Protocol Buffers. Dynamic compilation fails (uses new Function). Use protobufjs/light with pre-compiled static modules from pbjs CLI.
Error: Dynamic compilation uses new Function() - pre-compile protos instead
import protobuf from 'protobufjs/light';
// Usage: Use protobufjs/light with pre-compiled protos
// Pre-compile with: pbjs -t static-module -o proto.js *.proto
const root = new protobuf.Root();
return { success: true, result: { note: 'Pre-compile .proto files with pbjs CLI' } };
Parse proxy addresses from request headers
import proxyAddr from 'proxy-addr';
// Usage:
// Create mock request object
const req = {
connection: { remoteAddress: '127.0.0.1' },
headers: { 'x-forwarded-for': '203.0.113.195, 70.41.3.18, 150.172.238.178' }
};
// Parse proxy address with trust function
const addr = proxyAddr(req, () => true);
return {
success: addr === '203.0.113.195',
result: { address: addr }
};
Minimal pull-stream implementation
import pull from 'pull-stream';
// Usage:
const result = [];
pull(
pull.values([1, 2, 3]),
pull.map(x => x * 2),
pull.drain(x => result.push(x))
);
return { success: result.length === 3 && result[0] === 2, result };
Pipe streams together with proper error handling
import pump from 'pump';
// Usage:
const { Readable, Writable } = await import('node:stream');
const source = Readable.from(['hello', ' ', 'world']);
const chunks: string[] = [];
const dest = new Writable({
write(chunk, encoding, callback) {
chunks.push(chunk.toString());
callback();
}
});
await new Promise((resolve, reject) => {
pump(source, dest, (err) => {
if (err) reject(err);
else resolve(undefined);
});
});
return {
success: chunks.join('') === 'hello world',
result: chunks.join('')
};
Promise library (use native Promises instead)
import Q from 'q';
// Usage:
const deferred = Q.defer();
setTimeout(() => deferred.resolve('hello'), 10);
const result = await deferred.promise;
return {
success: result === 'hello',
result
};
import qs from 'qs';
// Usage:
const parsed = qs.parse('a=1&b=2');
const stringified = qs.stringify({ c: 3, d: 4 });
return { success: true, result: { parsed, stringified } };
import queryString from 'query-string';
// Usage:
const parsed = queryString.parse('a=1&b=2');
return { success: true, result: parsed };
Query string parsing (use URLSearchParams instead)
import querystring from 'querystring';
// Usage:
const parsed = querystring.parse('foo=bar&abc=xyz&abc=123');
const stringified = querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'] });
return {
success: parsed.foo === 'bar' && stringified.includes('foo=bar'),
result: { parsed, stringified }
};
Simple LRU cache implementation
import QuickLRU from 'quick-lru';
// Usage:
const lru = new QuickLRU({ maxSize: 100 });
lru.set('foo', 'bar');
lru.set('hello', 'world');
return {
success: lru.has('foo') && lru.get('foo') === 'bar' && lru.get('hello') === 'world',
result: { foo: lru.get('foo'), hello: lru.get('hello'), size: lru.size }
};
requestAnimationFrame polyfill
import raf from 'raf';
// Usage:
let executed = false;
const id = raf(() => { executed = true; });
// Wait a bit for the callback to execute
await new Promise(resolve => setTimeout(resolve, 50));
return {
success: executed,
result: { executed, id }
};
import * as R from 'ramda';
// Usage:
const result = R.map(x => x * 2, [1, 2, 3]);
return { success: true, result };
Crypto random bytes generation
import randomBytes from 'randombytes';
// Usage:
const bytes = randomBytes(16);
return { success: bytes.length === 16, result: { length: bytes.length } };
Random string generation
import randomstring from 'randomstring';
// Usage:
const str = randomstring.generate(10);
return { success: str.length === 10, result: { length: str.length, sample: str } };
Parse HTTP Range header (used in streaming/partial content)
import rangeParser from 'range-parser';
// Usage:
const result = rangeParser(1000, 'bytes=0-499');
return { success: Array.isArray(result) && result[0].start === 0 && result[0].end === 499, result };
Flexible rate limiter. Use memory store in Workers, or integrate with Durable Objects for distributed rate limiting.
π‘ Alternative: Durable Objects, Workers Rate Limiting API
import { RateLimiterMemory } from 'rate-limiter-flexible';
// Usage:
const limiter = new RateLimiterMemory({ points: 5, duration: 1 });
const res = await limiter.consume('user-1', 1);
return { success: res.remainingPoints === 4, result: { remaining: res.remainingPoints } };
Get raw body from a stream. For most cases, use native Request.text() or Request.arrayBuffer() instead.
π‘ Alternative: Request.text() or stream.text()
import getRawBody from 'raw-body';
import { Readable } from 'node:stream';
// Usage:
const stream = Readable.from(['Hello ', 'World']);
const body = await getRawBody(stream, { encoding: 'utf8' });
return { success: body === 'Hello World', result: { body } };
Configuration file loader with defaults
import rc from 'rc';
// Usage:
const config = rc('myapp', { port: 8080, host: 'localhost' });
return { success: config.port === 8080 && config.host === 'localhost', result: config };
Node.js streams polyfill. Workers has node:stream built-in with nodejs_compat.
π‘ Alternative: node:stream
Official Redis client for Node.js. Works with TCP connections in Workers. Consider @upstash/redis for HTTP-based Redis.
π‘ Alternative: @upstash/redis
Error: Unexpected token ':'
import { createClient } from 'redis';
const client = createClient({ url: 'redis://your-redis-server:6379' });
await client.connect();
await client.set('key', 'value');
const value = await client.get('key');
return { success: true, value };
Redux state management - can be used in Workers
import { createStore } from 'redux';
// Usage:
const reducer = (state = 0, action) => action.type === 'INC' ? state + 1 : state;
const store = createStore(reducer);
store.dispatch({ type: 'INC' });
return { success: store.getState() === 1, result: store.getState() };
Redux logging middleware
import { createLogger } from 'redux-logger';
// Usage:
const logger = createLogger();
return { success: typeof logger === 'function', result: { isFunction: typeof logger === 'function' } };
Redux middleware for side effects
import createSagaMiddleware from 'redux-saga';
// Usage:
const sagaMiddleware = createSagaMiddleware();
return { success: typeof sagaMiddleware === 'function', result: { isFunction: typeof sagaMiddleware === 'function' } };
Redux middleware for async actions
import { thunk } from 'redux-thunk';
// Usage:
const middleware = thunk;
return { success: typeof middleware === 'function', result: { isFunction: typeof middleware === 'function' } };
Metadata reflection API for decorators
import 'reflect-metadata';
// Usage:
const metadataKey = Symbol('test');
class Test {}
Reflect.defineMetadata(metadataKey, 'value', Test);
const result = Reflect.getMetadata(metadataKey, Test);
return { success: result === 'value', result };
Generate JavaScript-compatible regular expressions
import regenerate from 'regenerate';
// Usage:
const set = regenerate().addRange(0x61, 0x7A); // a-z
const result = set.toString();
return { success: result.includes('[a-z]'), result };
Runtime for generators/async functions (often unnecessary in modern Workers)
import 'regenerator-runtime/runtime';
// Usage:
async function* asyncGen() { yield 1; yield 2; }
const gen = asyncGen();
const result = await gen.next();
return { success: result.value === 1, result: result.value };
request is deprecated (archived since 2020) and tries to run async operations at import time which violates Workers' global scope restrictions. Use the built-in fetch API instead, which is the modern standard for HTTP requests.
π‘ Alternative: fetch (built-in) or node:http with nodejs_compat
Error: Disallowed operation called within global scope. Asynchronous I/O (ex: fetch() or connect()), setting a timeout, and generating random values are not allowed within global scope. To fix this error, pe
DEPRECATED but works. Promise wrapper for request. Use fetch or ky instead.
π‘ Alternative: ky
Error: No such module "node:os".
import rp from 'request-promise';
const data = await rp({ uri: 'https://api.example.com', json: true });
return { success: true, data };
Deprecated HTTP client - use fetch/ky/wretch
π‘ Alternative: ky
Error: Unexpected token ':'
Memoized selectors for Redux
import { createSelector } from 'reselect';
// Usage:
const selectItems = state => state.items;
const selectTotal = createSelector(
[selectItems],
items => items.reduce((sum, item) => sum + item, 0)
);
const state = { items: [1, 2, 3, 4] };
const result = selectTotal(state);
return { success: result === 10, result };
Node.js module resolution. isCore() works; sync/async resolve need filesystem access.
import resolve from 'resolve';
// Usage:
const fsIsCore = resolve.isCore('fs');
const fakeIsCore = resolve.isCore('nonexistent');
return { success: fsIsCore && !fakeIsCore, result: { fsIsCore, fakeIsCore } };
Node.js HTTP framework using process.binding - use hono or itty-router for Workers
π‘ Alternative: hono
Old HTTP client - use native fetch or modern alternatives
π‘ Alternative: fetch/ky/hono
Fast deep cloning utility
import rfdc from 'rfdc';
// Usage:
const clone = rfdc();
const obj = { a: 1, b: { c: 2 } };
const cloned = clone(obj);
cloned.b.c = 3;
return {
success: obj.b.c === 2 && cloned.b.c === 3,
result: { original: obj, cloned }
};
Promise library (native promises preferred)
import { Promise as RSVPPromise } from 'rsvp';
// Usage:
const p = new RSVPPromise((resolve) => resolve(42));
const result = await p;
return { success: result === 42, result };
Reactive extensions for JavaScript
import { of, map } from 'rxjs';
// Usage:
const observable = of(1, 2, 3).pipe(
map(x => x * 2)
);
let result = [];
await new Promise((resolve) => {
observable.subscribe({
next: value => result.push(value),
complete: () => resolve(undefined)
});
});
return { success: result.join(',') === '2,4,6', result };
Compatibility layer for older RxJS - use rxjs@7+ directly
π‘ Alternative: rxjs
Safe Buffer API (use native Buffer)
import { Buffer } from 'safe-buffer';
// Usage:
const buf = Buffer.from('hello', 'utf8');
const result = buf.toString('base64');
return { success: result === 'aGVsbG8=', result };
import sanitize from 'sanitize-filename';
// Usage:
const result = sanitize('hello/world.txt');
return { success: result === 'helloworld.txt', result };
HTML sanitizer to prevent XSS attacks
import sanitizeHtml from 'sanitize-html';
// Usage:
const dirty = '<div><script>alert("xss")</script><p>Safe content</p></div>';
const clean = sanitizeHtml(dirty);
return { success: !clean.includes('script') && clean.includes('Safe content'), result: clean };
import sax from 'sax';
// Usage:
const parser = sax.parser(true);
let tagName = '';
parser.onopentag = (node) => { tagName = node.name; };
parser.write('<xml>').close();
return { success: tagName === 'xml', result: tagName };
Native C++ bindings - use @noble/secp256k1 for pure JS implementation
π‘ Alternative: @noble/secp256k1
Semantic version parser and comparator
import semver from 'semver';
// Usage:
const valid = semver.valid('1.2.3');
const gt = semver.gt('2.0.0', '1.0.0');
const satisfies = semver.satisfies('1.5.0', '^1.0.0');
return { success: valid === '1.2.3' && gt === true && satisfies === true, result: { valid, gt, satisfies } };
Node.js ORM - use D1 with @cloudflare/d1 instead
π‘ Alternative: @cloudflare/d1
Serialize Error objects to JSON-friendly format
import { serializeError } from 'serialize-error';
// Usage:
const error = new Error('Test error');
error.name = 'TestError';
const serialized = serializeError(error);
return { success: serialized.message === 'Test error' && serialized.name === 'TestError', result: serialized };
SerialPort requires native C++ bindings for hardware serial port access. Not applicable to Workers.
π‘ Alternative: Workers can communicate with hardware via HTTP APIs or Workers IoT device integrations
Error: Command failed: npm install npm warn tar ENOENT: Cannot cd into '/Users/steve/works-on-workers/packages/test-harness/sandbox/serialport/node_modules/tinyspy' npm warn tar ENOENT: Cannot cd into '/User
Express middleware for serving favicon. Depends on Node.js stream internals. For favicons in Workers, use Static Assets to serve favicon.ico directly, or embed as base64 in your code.
π‘ Alternative: Workers Static Assets or embed favicon as base64
Error: no such file or directory, stat
Express middleware for directory listings. Depends on Node.js stream internals not fully supported in Workers. For directory listing functionality, implement custom logic with Workers Static Assets or R2.
π‘ Alternative: Workers Static Assets with custom directory listing
Error: Could not resolve emitter
Express/Connect middleware for serving static files. While node:fs now works in Workers, serve-static depends on Node.js stream internals that are not fully compatible. Use Workers Static Assets instead - it is the built-in, optimized solution for serving static files.
π‘ Alternative: Workers Static Assets (https://developers.cloudflare.com/workers/static-assets/)
Error: ENOENT: no such file or directory
import sha1 from 'sha1';
// Usage:
const result = sha1('hello');
return { success: result === 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d', result };
import shallowEqual from 'shallowequal';
// Usage:
const result = shallowEqual({ a: 1, b: 2 }, { a: 1, b: 2 });
return { success: result === true, result };
sharp is a native module with C++ bindings (uses libvips) that requires node:child_process and won't work in Workers. Use Cloudflare Images API for image transformations, or consider browser-based image libraries like pica or jimp for client-side processing.
π‘ Alternative: Cloudflare Images or @cloudflare/workers-image (when available)
Error: No such module "node:child_process".
import { parse } from 'shell-quote';
// Usage:
const result = parse('echo "hello world"');
return { success: result.length === 2, result };
Short UUID generator using base58
import shortUUID from 'short-uuid';
// Usage:
// Test the generate function
const uuid = shortUUID.generate();
const isValid = typeof uuid === 'string' && uuid.length > 0;
return { success: isValid, result: { uuid } };
Deprecated package with issues
π‘ Alternative: nanoid
Error: Cannot read properties of undefined (reading 'random')
Markdown to HTML converter
import { Converter } from 'showdown';
// Usage:
const converter = new Converter();
const html = converter.makeHtml('# Hello World');
return { success: html.includes('<h1') && html.includes('Hello World'), result: html };
Convert Windows backslashes to forward slashes
import slash from 'slash';
// Usage:
const result = slash('foo\\bar\\baz');
return { success: result === 'foo/bar/baz', result };
URL slug generator
import slug from 'slug';
// Usage:
const result = slug('Hello World!');
return { success: result === 'hello-world', result };
import slugify from 'slugify';
// Usage:
const slug = slugify('Hello World!');
return { success: slug === 'Hello-World!', result: slug };
SOAP client for calling WSDL web services. Use namespace import: import * as soap from "soap"
import * as soap from 'soap';
// Usage:
const hasClient = typeof soap.createClientAsync === 'function';
const securityTypes = ['BasicAuthSecurity', 'BearerSecurity', 'WSSecurity'];
return { success: hasClient, result: { securityTypes, note: 'Use createClientAsync(wsdlUrl) to create SOAP client' } };
Use Durable Objects + WebSockets or PartyKit instead
π‘ Alternative: Durable Objects/PartyKit
WebSocket client - use native WebSocket or Durable Objects
π‘ Alternative: Durable Objects/PartyKit
Error: No such module "node:child_process".
Library for working with source maps
import { SourceMapConsumer } from 'source-map';
// Usage:
// Test that SourceMapConsumer is available
const hasConsumer = typeof SourceMapConsumer === 'function';
return { success: hasConsumer, result: { hasConsumer } };
Fixes stack traces for files with source maps
import sourceMapSupport from 'source-map-support';
// Usage:
// Install source map support
sourceMapSupport.install();
return { success: true, result: 'installed' };
Split text streams into line streams
import split from 'split';
// Usage:
// Split is a stream transformer
const hasSplit = typeof split === 'function';
return { success: hasSplit, result: { hasSplit } };
Split streams by newline
import split from 'split2';
// Usage:
const stream = split();
return { success: typeof stream.pipe === 'function', result: 'stream created' };
String formatting library (sprintf)
import { sprintf } from 'sprintf-js';
// Usage:
const result = sprintf('Hello %s!', 'World');
return { success: result === 'Hello World!', result };
Native C++ module - use D1 or @libsql/client instead
π‘ Alternative: D1/@libsql/client
Get V8 stack traces as structured data. Use namespace import: import * as stackTrace
import * as stackTrace from 'stack-trace';
// Usage:
const err = new Error('test');
const trace = stackTrace.parse(err);
return { success: trace.length > 0, result: { frames: trace.length } };
HTTP status code utilities. Get status codes by message or message by code.
import statuses from 'statuses';
// Usage:
const code = statuses('OK');
const msg = statuses(404);
return { success: code === 200 && msg === 'Not Found', result: { code, msg } };
String manipulation library
import S from 'string';
// Usage:
const result = S('hello world').capitalize().s;
return { success: result === 'Hello world', result };
Strip ANSI escape codes from strings
import stripAnsi from 'strip-ansi';
// Usage:
const result = stripAnsi('\u001b[31mHello\u001b[0m');
return { success: result === 'Hello', result };
Strip comments from JSON strings. Useful for parsing JSON config files with comments.
import stripJsonComments from 'strip-json-comments';
// Usage:
const jsonWithComments = '{ "name": "test" /* comment */ }';
const clean = stripJsonComments(jsonWithComments);
const parsed = JSON.parse(clean);
return { success: parsed.name === 'test', result: parsed };
HTTP client library - import issues with Workers runtime
π‘ Alternative: fetch API, ky, or ofetch
Error: request2.agent is not a function
JSON serializer with support for Date, Set, Map, etc.
import superjson from 'superjson';
// Usage:
const data = { date: new Date('2026-01-10'), set: new Set([1, 2, 3]) };
const serialized = superjson.stringify(data);
const deserialized = superjson.parse(serialized);
return { success: deserialized.date instanceof Date && deserialized.set instanceof Set, result: { serialized } };
Data validation library
import { object, string, number } from 'superstruct';
// Usage:
const User = object({ name: string(), age: number() });
try {
const result = User.create({ name: 'Alice', age: 30 });
return { success: result.name === 'Alice', result };
} catch (e) {
return { success: false, result: e.message };
}
Detect terminal color support
import supportsColor from 'supports-color';
// Usage:
const result = supportsColor.stdout;
return { success: true, result: { hasBasic: result !== false } };
Synchronous HTTP requests (blocking). Use native fetch() instead
π‘ Alternative: fetch
Generate text tables
import table from 'text-table';
// Usage:
const t = table([['master', 'now', 'origin/master'], ['0.1.0', '4 minutes ago']]);
return { success: t.includes('master'), result: t };
Throttle and debounce functions
import { throttle, debounce } from 'throttle-debounce';
// Usage:
const fn = () => 42;
const throttled = throttle(100, fn);
const debounced = debounce(100, fn);
return { success: typeof throttled === 'function' && typeof debounced === 'function', result: { throttled: typeof throttled, debounced: typeof debounced } };
Stream transformer utility
import through from 'through';
// Usage:
// through is a stream transformer
const stream = through((data) => data);
return { success: typeof stream.write === 'function', result: { hasWrite: typeof stream.write } };
Stream transformer utility (wrapper for through)
import through2 from 'through2';
// Usage:
// through2 is a stream transformer
const stream = through2((chunk, enc, callback) => {
callback(null, chunk);
});
return { success: typeof stream.write === 'function', result: { hasWrite: true } };
Lightweight event emitter
import Emitter from 'tiny-emitter';
// Usage:
const emitter = new Emitter();
let called = false;
emitter.on('test', () => { called = true; });
emitter.emit('test');
return { success: called, result: { emitted: called } };
Assertion utility
import invariant from 'tiny-invariant';
// Usage:
try {
invariant(true, 'should not throw');
invariant(false, 'should throw');
return { success: false, result: 'did not throw' };
} catch (e) {
return { success: true, result: 'threw as expected' };
}
Color manipulation library
import tinycolor from 'tinycolor2';
// Usage:
const color = tinycolor('#ff0000');
const hex = color.toHexString();
return { success: hex === '#ff0000', result: hex };
import TOML from 'toml';
// Usage:
const obj = TOML.parse('name = "Alice"\nage = 30');
return { success: true, result: obj };
HTTP cookie parsing and storage
import { Cookie } from 'tough-cookie';
// Usage:
const cookie = Cookie.parse('foo=bar; Path=/; Domain=example.com');
return { success: cookie && cookie.key === 'foo' && cookie.value === 'bar', result: { key: cookie?.key, value: cookie?.value } };
Object traversal utility
import traverse from 'traverse';
// Usage:
const obj = { a: 1, b: { c: 2 } };
const result = traverse(obj).map(function(x) {
if (typeof x === 'number') this.update(x * 2);
});
return { success: result.a === 2 && result.b.c === 4, result };
TypeScript utility types (no runtime)
// ts-essentials is type-only
// Usage:
return { success: true, result: 'ts-essentials is type-only' };
TypeScript runtime helpers
import * as tslib from 'tslib';
// Usage:
return { success: typeof tslib.__extends === 'function', result: { hasExtends: true } };
Cryptography library for signing, encryption, and hashing
import nacl from 'tweetnacl';
// Usage:
const pair = nacl.sign.keyPair();
const message = new Uint8Array([1, 2, 3]);
const signed = nacl.sign(message, pair.secretKey);
const opened = nacl.sign.open(signed, pair.publicKey);
return { success: opened !== null && opened.length === 3, result: 'signature verified' };
Content-Type checking utility. Used by body-parser and Express middleware.
import typeis from 'type-is';
const isJson = typeis.is('application/json', ['json']); // 'json'
const isHtml = typeis.is('text/html', ['html']); // 'html'
return { success: isJson === 'json' };
import { ulid } from 'ulid';
// Usage:
const id = ulid();
return { success: id.length === 26, result: id };
import _ from 'underscore';
// Usage:
const result = _.flatten([[1, 2], [3, 4]]);
return { success: true, result };
String manipulation utilities
import s from 'underscore.string';
// Usage:
const result = s.capitalize('hello');
return { success: result === 'Hello', result };
Use native fetch() API in Workers
Install failed - use crypto.getRandomValues()
π‘ Alternative: crypto.getRandomValues()
AST utility for traversing unist trees
import { visit } from 'unist-util-visit';
// Usage:
const tree = { type: 'root', children: [{ type: 'text', value: 'hello' }] };
const values: string[] = [];
visit(tree, 'text', (node: any) => values.push(node.value));
return { success: values[0] === 'hello', result: values };
Feature flag client - use @cloudflare/workers-sdk
π‘ Alternative: Cloudflare Workers Environment Variables or KV
Requires process.binding - use fflate or pako
π‘ Alternative: fflate, pako
URI parsing and manipulation
import URI from 'urijs';
// Usage:
const uri = new URI('http://example.com/path?query=value');
return { success: uri.hostname() === 'example.com', result: { host: uri.hostname(), path: uri.path() } };
Use built-in node:url module or URL global
Error: __vite_ssr_import_0__.parse is not a function
URL path joining utility
import urljoin from 'url-join';
// Usage:
const result = urljoin('https://example.com', 'path', 'to', 'file.html');
return { success: result === 'https://example.com/path/to/file.html', result };
URL parsing library
import URL from 'url-parse';
// Usage:
const parsed = new URL('https://example.com/path?q=1');
return { success: parsed.hostname === 'example.com', result: { hostname: parsed.hostname } };
HTTP client for Node.js - use fetch or ky instead
π‘ Alternative: fetch / ky
Error: Package urllib needs manual test configuration - do not use generic Object.keys() test
UTF-8 encoding/decoding
import utf8 from 'utf8';
// Usage:
const encoded = utf8.encode('hello');
const decoded = utf8.decode(encoded);
return { success: decoded === 'hello', result: { encoded, decoded } };
Node.js util module
import * as util from 'util';
// Usage:
const result = util.format('Hello %s', 'World');
return { success: result === 'Hello World', result };
Simple object merging utility
import merge from 'utils-merge';
// Usage:
const result = merge({ a: 1 }, { b: 2 });
return { success: result.a === 1 && result.b === 2, result };
import { v4 as uuidv4, validate } from 'uuid';
// Usage:
const id = uuidv4();
const isValid = validate(id);
return { success: isValid, result: id };
import * as v from 'valibot';
// Usage:
const schema = v.object({ name: v.string() });
const result = v.safeParse(schema, { name: 'Alice' });
return { success: result.success, result: result.output };
URL validation
import validUrl from 'valid-url';
// Usage:
const valid = validUrl.isUri('http://example.com');
const invalid = validUrl.isUri('not a url');
return { success: valid && !invalid, result: { valid, invalid } };
Validate npm package names according to npm registry rules.
import validate from 'validate-npm-package-name';
// Usage:
const valid = validate('my-package');
const invalid = validate('INVALID NAME');
return { success: valid.validForNewPackages && !invalid.validForNewPackages, result: { valid: valid.validForNewPackages, errors: invalid.errors } };
String validation library
import validator from 'validator';
// Usage:
const email = validator.isEmail('test@example.com');
const notEmail = validator.isEmail('not-an-email');
return { success: email && !notEmail, result: { email, notEmail } };
HTTP Vary header utility
import vary from 'vary';
// Usage:
// vary.append() appends field to header value
const result = vary.append('Accept', 'Accept-Encoding');
return { success: result === 'Accept, Accept-Encoding', result };
Rich error objects
import VError from 'verror';
// Usage:
const err = new VError('test error');
return { success: err.message === 'test error', result: { message: err.message } };
import warning from 'warning';
// Usage:
// warning is a dev-only warning utility
// Just check that it's a function
const result = typeof warning === 'function';
warning(true, 'This should not warn');
return { success: result, result: 'warning is callable' };
Ethereum library
π‘ Alternative: viem or ethers
Error: No such module "Users/steve/works-on-workers/packages/test-harness/sandbox/web3/node_modules/web3-providers-ws/lib/esm/isomorphic-ws".
WebSocket client
π‘ Alternative: WebSocket API (built-in to Workers)
Error: Unexpected token ':'
winston requires node:os API which is not available in Workers. Use console.log/error for simple logging, or pino with cloudflare transport for structured logging.
π‘ Alternative: console or pino-cloudflare
Error: No such module "node:os".
import * as XLSX from 'xlsx';
// Usage:
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.aoa_to_sheet([['Name', 'Age'], ['Alice', 30]]);
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
const csv = XLSX.utils.sheet_to_csv(ws);
return { success: csv.includes('Alice'), result: csv };
import { parseString } from 'xml2js';
// Usage:
let result: any;
parseString('<root><name>test</name></root>', (err, res) => { result = res; });
return { success: result?.root?.name?.[0] === 'test', result };
import builder from 'xmlbuilder';
// Usage:
const xml = builder.create('root').ele('name', 'test').end();
return { success: xml.includes('<name>test</name>'), result: xml };
XML DOM parser and serializer. Parse and manipulate XML documents in Workers.
import { DOMParser, XMLSerializer } from '@xmldom/xmldom';
const parser = new DOMParser();
const doc = parser.parseFromString('<root><item>test</item></root>', 'text/xml');
const item = doc.getElementsByTagName('item')[0].textContent;
return { success: item === 'test', item };
Old XHR polyfill, requires child_process
π‘ Alternative: fetch API (built-in)
Error: No such module "node:child_process".
Extended regular expressions with Unicode support, named capture groups, and more.
import XRegExp from 'xregexp';
// Usage:
const pattern = XRegExp('(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})');
const match = XRegExp.exec('2026-01-08', pattern);
return { success: match.groups.year === '2026', result: match.groups };
import xtend from 'xtend';
// Usage:
const result = xtend({ a: 1 }, { b: 2 }, { c: 3 });
return { success: result.a === 1 && result.b === 2 && result.c === 3, result };
import YAML from 'yaml';
// Usage:
const obj = { name: 'test', age: 30 };
const str = YAML.stringify(obj);
const parsed = YAML.parse(str);
return { success: parsed.name === 'test' && parsed.age === 30, result: parsed };
import YAML from 'yamljs';
// Usage:
const obj = { name: 'test', age: 30 };
const str = YAML.stringify(obj);
const parsed = YAML.parse(str);
return { success: parsed.name === 'test' && parsed.age === 30, result: parsed };
import * as yup from 'yup';
// Usage:
const schema = yup.object({ name: yup.string().required() });
const result = await schema.validate({ name: 'Alice' });
return { success: true, result };
import { z } from 'zod';
// Usage:
const schema = z.object({ name: z.string(), age: z.number() });
const result = schema.safeParse({ name: 'Alice', age: 30 });
return { success: result.success, result: result.data };
Many popular npm packages are build tools (webpack, babel), test frameworks (jest, mocha), or CLI utilities (chalk, commander) that run during developmentβnot in production. Cloudflare Workers is a runtime environment for production code. These tools still work great for building your Workers project, they just don't run inside Workers themselves.
Yes! As of September 2025, Workers supports node:http server APIs.
Use httpServerHandler from cloudflare:node to wrap Express, Koa, or other Node.js HTTP frameworks.
For new projects, we recommend lightweight alternatives like Hono or itty-router which are built for edge environments.
Workers supports database clients like pg (PostgreSQL) and mysql2 when connecting to public endpoints.
For production, use edge-optimized solutions: Cloudflare D1 (SQLite), Neon (serverless Postgres), PlanetScale (MySQL), or Upstash Redis.
Common reasons: Native modules (C++ bindings like sharp, bcrypt) don't workβuse alternatives like bcryptjs or Cloudflare Images.
Filesystem access (fs module for local files) isn't availableβuse KV, R2, or D1 instead.
TCP sockets (raw socket.io, redis) aren't supportedβuse Durable Objects, WebSockets, or HTTP-based alternatives.