npm package: @ideadesignmedia/webserver.js
Description: Express-based webserver utilities with proxy, storage, and security helpers.
Author: ideadesignmedia
Latest version: 2.0.2

# webserver.js
A strongly typed TypeScript toolkit for building Express-based web servers, HTTP proxies, and companion middleware. The package publishes both ESM and CommonJS builds so it can be consumed from any modern Node.js project.

## Highlights
- Source written in TypeScript with strict typing and emitted declaration files.
- Dual `module`/`main` exports (`dist/esm` and `dist/cjs`) for seamless ESM or CJS usage.
- Express server bootstrapper with automatic gzip static serving, sanitization, and error logging.
- Ready-to-use proxy helpers: direct proxy, round-robin load balancer, and race proxy.
- Optional utilities including Backblaze filestore routes, brute-force protection, visit logging, uploads, and request transformer routing.

## Installation
```bash
npm install @ideadesignmedia/webserver.js
# or
yarn add @ideadesignmedia/webserver.js
```

## Building locally
```bash
npm run build
```
This command clears the `dist` directory and emits both CommonJS and ESM output plus type declarations.

## Quick start
```ts
import createServer, { createProxyServer, upload, visitsMiddleware } from '@ideadesignmedia/webserver.js';
import express from 'express';

const router = express.Router();
router.get('/health', (_req, res) => res.json({ ok: true }));

const server = createServer({ port: 3000, static: './public' }, router, [visitsMiddleware]);

createProxyServer({
  target: 'https://api.example.com',
}).listen(3100);
```

### CommonJS quick start
```js
const webserver = require('@ideadesignmedia/webserver.js');
const express = require('express');

const createServer = webserver.default;
const { createProxyServer, upload, visitsMiddleware } = webserver;

const router = express.Router();
router.get('/health', (_req, res) => res.json({ ok: true }));

const server = createServer({ port: 3000, static: './public' }, router, [visitsMiddleware]);

createProxyServer({
  target: 'https://api.example.com',
  port: 3100,
});
```

## Proxy helpers
All proxy helpers share the same strongly typed header filtering and optional error handling hooks.

### Direct proxy
```ts
import { startProxyServer } from '@ideadesignmedia/webserver.js';

startProxyServer({
  target: 'https://internal.service',
  port: 3200,
});
```
Environment fallbacks: set `PROXY_SERVER_TARGET` (and optionally `PROXY_SERVER_PORT`).

### Load balancer
```ts
import { startLoadBalancerServer } from '@ideadesignmedia/webserver.js';

startLoadBalancerServer({
  targets: ['https://api-1.example', 'https://api-2.example'],
  port: 3300,
});
```
Environment fallback keys: `LOAD_BALANCER_TARGETS` or `PROXY_HOSTS` (comma-separated) and `LOAD_BALANCER_PORT`.

### Race proxy
```ts
import { startRaceServer } from '@ideadesignmedia/webserver.js';

startRaceServer({
  targets: ['https://global-a.example', 'https://global-b.example'],
  port: 3400,
});
```
Environment fallback keys: `RACE_SERVER_TARGETS` or `PROXY_HOSTS`, plus `RACE_SERVER_PORT` (default `PORT`).

## Filestore routing
```ts
import { createFilestoreRouter } from '@ideadesignmedia/webserver.js';

const filestore = createFilestoreRouter({
  DBNAME: 'filestore',
  BBID: process.env.BACKBLAZE_ID,
  BBKEY: process.env.BACKBLAZE_KEY,
  BUCKET: process.env.BACKBLAZE_BUCKET,
}, async req => {
  if (!req.isUser) {
    throw new Error('Unauthorized');
  }
});
```
`createFilestoreRouter` pairs with the bundled `upload` middleware and Backblaze helper. It enforces authenticated access when `FileRecord.public` is false and automatically queues uploads to Backblaze while cleaning up local files.

## Available exports
```
createServer (default)
createProxyServer / startProxyServer / startProxyServerFromEnv
createLoadBalancerServer / startLoadBalancerServer / startLoadBalancerFromEnv
createRaceServer / startRaceServer / startRaceServerFromEnv
createFilestoreRouter
requestTransformer (Express router)
visitsMiddleware
upload
bruteForce helpers: checkAttempts, addAttempt, resetAttempts
saveError
```

## Environment helpers
The optional `@ideadesignmedia/config.js` package may still be used to populate `process.env` (e.g., by providing a `config.json`). All runtime configuration ultimately resolves from environment variables, so each helper validates inputs before handling requests to prevent runtime crashes.

## License
MIT