Skip to content

Latest commit

 

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DegreeSign Server SDK

Zero-framework, TypeScript REST API server SDK built directly on Node's native node:http module — routing, CORS, JSON body parsing, AES-256 encryption, HMAC, hCaptcha, TOTP, cache and file helpers in one non-opinionated package.

npm version npm downloads License: MIT TypeScript Node.js PRs welcome

Table of Contents

What is DegreeSign Server SDK?

DegreeSign Server SDK is a lightweight TypeScript REST API server SDK that lets you stand up a working HTTP API server in a few lines of code without Express or any other web framework. It is built directly on Node's native http module — importing IncomingMessage, ServerResponse and createServer — and works with Node primitives such as Buffer, req.socket, server.listen(), requestTimeout, headersTimeout and keepAliveTimeout. Alongside the framework-free router it bundles a set of small, server-side helpers for encryption, HMAC, captcha verification, TOTP codes, string sanitisation, file/cache access and outbound HTTP, all behind the same package. It is framework-free, dependency-light, fully typed, and designed to run behind a TLS-terminating reverse proxy.

Why DegreeSign Server SDK?

  • Free forever under MIT. No paid tier, trial, seat limit or usage cap — use it in personal and commercial projects.
  • No signup or account required. Install from npm and start building — there is no registration, account, API key or license key.
  • No Express, no framework lock-in. Runs on node:http primitives, so there is nothing to rewrite when Node evolves.
  • Instant REST API setup. Register GET / POST routes with a plain array of objects and go live with startListener.
  • Automatic JSON handling. Request bodies are parsed as JSON when the Content-Type is application/json; query strings are parsed into an object for GET.
  • CORS built in. OPTIONS preflight responses are handled automatically and allowedOrigins restricts cross-origin access.
  • Secure by default. Configurable body limits (maxBodySizeMB), request/header timeouts and slowloris/slow-body protection.
  • Batteries included. AES-256-CBC encryption, HMAC, hCaptcha verification, TOTP/API codes, sanitisation, cache, disk and download helpers ship in the box.
  • Fully typed in TypeScript. Written in TypeScript and ships declaration files for excellent autocomplete and IntelliSense.
  • Tiny and tree-shakeable. Bundled, minified, marked side-effect free, and published with a single dependency tree.
  • Easy to monitor. Logging, processing and response helpers (rf, ff) make consistent JSON responses trivial.

Installation

npm

npm install @degreesign/server

yarn

yarn add @degreesign/server

pnpm

pnpm add @degreesign/server

Quick Start

The example below is complete and copy-paste ready. It starts a CORS-aware REST API with a GET health route and a POST echo route on port 1234.

1. Start a server

import {
    startListener,
    rf,
    APIData,
    ListenerSpecs,
    ProcessInputs,
} from "@degreesign/server";

interface AccessData extends ProcessInputs {
    body: any;
}

// Runs for every request: logging, auth, rate limiting, etc.
const listenProcessor = ({ endPoint, ips, req, res, fun }: APIData<AccessData>) => {
    console.log(`processing`, endPoint);
    fun({ ips, req, res, body: req.body });
};

const listeners: ListenerSpecs<AccessData>[] = [
    {
        method: `GET`,
        endPoint: `health`, // GET /health -> { success: true, ... }
        task: `health check`,
        fun: ({ res }) => rf(res, { status: `ok`, uptime: process.uptime() }),
    },
    {
        method: `POST`,
        endPoint: `test`, // POST /test -> { success: true, received: { ... } }
        task: `testing API`,
        fun: ({ res, body }) => rf(res, { received: body }),
    },
];

startListener<AccessData>({
    port: 1234,
    allowedOrigins: [`https://example.com`, `http://localhost:1234`],
    listenProcessor,
    listeners,
});

2. Configure the server

setServerConfig tunes the server and the helper behaviour. Every field is optional and merged into the live serverConfig object.

import { setServerConfig } from "@degreesign/server";

setServerConfig({
    encryptionKey: process.env.ENCRYPTION_KEY,
    encryptionSalt: process.env.ENCRYPTION_SALT,
    captchaSecret: process.env.CAPTCHA_SECRET,
    cacheDir: `./.cache`,
    maxBodySizeMB: 10,
    requestTimeoutMs: 30_000,
    headersTimeoutMs: 60_000,
    keepAliveTimeoutMs: 5_000,
    maxRequestsPerSocket: 0, // 0 = unlimited
});

3. Call it from the client

// POST JSON — parsed into req.body on the server
const res = await fetch(`http://localhost:1234/test`, {
    method: `POST`,
    headers: { "Content-Type": `application/json` },
    body: JSON.stringify({ hello: `world` }),
});

console.log(await res.json()); // { success: true, received: { hello: "world" } }

4. Encryption, captcha and TOTP codes

import {
    setServerConfig,
    en,
    de,
    hmacValid,
    capVerify,
    genAPI,
    verAPI,
    genShortCode,
} from "@degreesign/server";

setServerConfig({
    encryptionKey: `your-32-character-encryption-key`,
    encryptionSalt: `your-encryption-salt`,
    captchaSecret: `your-hcaptcha-secret`,
});

const token = en(`secret payload`);       // hex ciphertext
const plain = de(token);                  // "secret payload"

const signature = hmacValid({ data: `payload`, secret: `shared-secret` });

const human = await capVerify(hCaptchaToken); // true | false | undefined

const secret = genAPI(20);                // base32 TOTP secret
const valid = verAPI(secret, userCode);   // true | false | undefined
const shortCode = genShortCode();         // base32 code of length 4

5. Files, cache and outbound HTTP

import {
    wrtJ,
    redJ,
    saveCache,
    readCache,
    saveFileLocally,
    getData,
} from "@degreesign/server";

wrtJ(`data.json`, { hello: `world` });
const data = redJ(`data.json`);

saveCache(`sessions`, { user: 1 });
const sessions = readCache(`sessions`);

await saveFileLocally({ url: `https://example.com/logo.png`, filePath: `./logo.png` });

const api = await getData(`https://api.example.com/data`);

API Reference

Server

Export Signature Description
startListener startListener<T>(options: { port: number; allowedOrigins?: string[]; listenProcessor: (p: APIData<T>) => any; listeners: ListenerSpecs<T>[] }): void Registers every listener and starts the native http server on port. Default listener method is POST.
rf rf(res: ServerResponse, data: any, success?: boolean): void Sends a 200 JSON response shaped { success, ...data }. When success is omitted it is derived from the absence of a .e property.
ff ff(res: ServerResponse): void Safely ends a connection with HTTP 504 Gateway Timeout; used for failed or timed-out requests.

Configuration

Export Signature Description
serverConfig ServerConfig The live, mutable configuration object used across the SDK.
getServerConfig getServerConfig(): ServerConfig Returns the current configuration object.
setServerConfig setServerConfig(config: Partial<ServerConfig>): void Merges a partial configuration; only valid values are applied.

ServerConfig accepts the following fields: cacheDir, encryptionKey, encryptionSalt, captchaSecret, sanitisationString, sanitisationStringExtended, overrideUserAgent, maxBodySizeMB, requestTimeoutMs, headersTimeoutMs, keepAliveTimeoutMs and maxRequestsPerSocket.

Types

Export Description
ServerConfig Configuration shape controlling encryption, captcha, cache, sanitisation and request hardening.
ProcessInputs Base request context: ips (resolved client IP), req (IncomingMessage with parsed body) and res (ServerResponse).
APIData<T> Per-request object handed to listenProcessor: extends ProcessInputs with endPoint and the route's fun.
ListenerSpecs<T> Route definition: method (GET | POST, default POST), endPoint, task and processing fun.

Encryption and HMAC

Export Signature Description
en en(data?: string): string Encrypts a UTF-8 string with aes-256-cbc and returns hex ciphertext.
de de(dataEN?: string): string Decrypts hex ciphertext produced by en back to a UTF-8 string.
hmacValid hmacValid({ data: string; secret: string; algorithm?: "sha512" | "sha256" }): string Returns a hex HMAC digest, defaulting to sha512.

Captcha

Export Signature Description
capVerify capVerify(token?: string): Promise<boolean | undefined> Verifies an hCaptcha token against captchaSecret using the bundled hcaptcha client.

API codes and TOTP

Export Signature Description
genAPI genAPI(length: number): string Generates a base32 secret of the given length for TOTP/API codes.
genRandomCodeSize genRandomCodeSize(): string Generates a base32 secret with a random length between 20 and 30.
genShortCode genShortCode(): string Generates a short base32 code (length 4).
verAPI verAPI(auth: string, t: string): boolean | undefined Verifies a TOTP token against a base32 secret.

Strings and validation

Export Signature Description
chkStg chkStg(txt?: string): string Sanitises a value against sanitisationString, returning a safe string or an empty string.
txtShort txtShort(txt?: string, len = 15): string Returns the last len characters of a string (useful for masking identifiers).
validLen validLen(len: number, txt?: string, checkNeg?: boolean): boolean Validates that a string is shorter than len, optionally rejecting matches of sanitisationStringExtended.
validLenEq validLenEq(len: number, txt?: string, checkNeg?: boolean): boolean Validates that a string is exactly len characters, optionally rejecting matches of sanitisationStringExtended.

Files, cache and disk

Re-exported from @degreesign/cache for convenience.

Export Signature Description
wrt wrt(file: string, code: any): boolean Writes a value to a file.
wrtJ wrtJ(file: string, code: any): 0 | 1 Writes a value to a file as JSON.
red red(file: string, disableLog?: boolean): string | undefined Reads a file as a string.
redJ redJ(file: string, disableLog?: boolean): any Reads and parses a JSON file.
safeFolder safeFolder(targetFolder: string): boolean Ensures/validates a folder path is safe to use.
delFolder delFolder(targetFolder: string): boolean Deletes a folder.
delFile delFile(file: string): true | undefined Deletes a file.
fileStats fileStats(targetFile: string): Stats | undefined Returns fs.Stats for a file.
saveCache saveCache(key: string, data: any): void Writes a value to the cache directory under key.
readCache readCache(key: string): any Reads a value from the cache directory by key.

Outbound HTTP and process

Export Signature Description
getData getData(url: string, body?: any, headersData?: any, noCache = true): Promise<any> Fetches JSON over HTTP/HTTPS; sends POST when a body is given, otherwise GET. Returns parsed JSON for 200/201/202, else undefined.
saveFileLocally saveFileLocally({ url: string; filePath: string }): Promise<boolean> Streams a remote file to a local path; resolves true on success.
cmd cmd(command: string): string | number Runs a shell command with execSync, returning its output, 1 when empty, or 0 on error.

Deployment behind Apache (HTTPS reverse proxy)

The SDK serves plain HTTP/1.1 and is meant to run behind a TLS-terminating reverse proxy. Let Apache own HTTPS and proxy cleartext HTTP to the SDK's port.

Apache Config

Enable the required modules (a2enmod ssl proxy proxy_http headers rewrite):

# Server IP and Node port
Define main_ip 127.0.0.1
Define port_api 1234

# Publicly accessible static files directory served directly by Apache
<Directory /var/www/public_data>
	Options -Indexes +FollowSymLinks
	AllowOverride All
	Require all granted
</Directory>

# HTTPS virtual host
<VirtualHost *:443>

    # Restrict Access
	<IfModule mod_headers.c>
		Header set Cache-Control "max-age=86400, public"
        <IfModule mod_rewrite.c>
            RewriteEngine On
            RewriteCond %{HTTP:Origin} ^(https://example\.com|http://localhost:${port_api}|https://localhost:${port_api})$ [NC]
            RewriteRule ^ - [E=ORIGIN:%{HTTP:Origin}]
            Header set Access-Control-Allow-Origin "%{ORIGIN}e" env=ORIGIN
        </IfModule>
    </IfModule>

    # Allow Unrestricted (useful for third-party access to a certain directory in public files)
    <Directory /var/www/public_data/shared>
		Header set Access-Control-Allow-Origin *
		Options -Indexes
	</Directory>

	# SSL (obtained from a trusted CA)
	SSLEngine on
	SSLCertificateFile /etc/cer/example/public.crt
	SSLCertificateKeyFile /etc/cer/example/private.key

	# Server data
	ServerName api.example.com
	ServerAdmin admin@example.com
	DocumentRoot /var/www/public_data
	ErrorDocument 404 https://example.com

	# Node ports
	ProxyPreserveHost On
	ProxyPass /api http://${main_ip}:${port_api}
	ProxyPassReverse /api http://${main_ip}:${port_api}
</VirtualHost>

Node listener

const port = 1234;
startListener<AccessData>({
    port,
    allowedOrigins: [`https://example.com`, `http://localhost:${port}`, `https://localhost:${port}`],
    listenProcessor,
    listeners,
});

Notes:

  • mod_proxy adds X-Forwarded-For; the SDK reads it to resolve the client IP.
  • ProxyPass strips the matched prefix, so register routes without /api (e.g. /test, not /api/test).
  • The SDK binds all interfaces; firewall its port so only the proxy can reach it.
  • Keep ProxyPass on http:// — the SDK does not terminate TLS.

Faster Request Header (frontend only)

To make browsers skip the OPTIONS (preflight) call, send the request with Content-Type: text/plain;charset=UTF-8;type=application/json. Because text/plain is a CORS "simple request" content type, the browser sends the request directly without a preflight.

const FASTER_HEADER: OutgoingHttpHeaders = {
    [`Content-Type`]: `text/plain;charset=UTF-8;type=application/json`,
};

fetch(`https://api.example.com/api/test`, {
    method: `POST`,
    headers: FASTER_HEADER,
    body: JSON.stringify({ hello: `world` }),
});

FAQ

What is DegreeSign Server SDK?

It is a TypeScript SDK for building a lightweight REST API server directly on Node's native node:http module, plus a small toolkit of server-side helpers (encryption, HMAC, hCaptcha, TOTP, sanitisation, cache, files and outbound HTTP).

Is DegreeSign Server SDK free?

Yes — it is free forever. It is open source and released under the MIT License, free for personal and commercial use, with no paid tier, trial period, seat limit or usage cap.

Do I need an account or signup to use it?

No. There is no signup, account, registration, API key or license key required — install it from npm and start building. Any optional third-party feature you enable (such as hCaptcha) uses your own provider credentials.

Does it work on Node.js and in the browser?

It is a Node.js server SDK (Node.js 18+ is required) and runs wherever Node's http, fs, crypto and child_process built-ins are available. It is not a browser library — it serves the API that browser apps call.

Does it have any dependencies?

Yes. Runtime dependencies are @degreesign/cache, @degreesign/utils, hcaptcha and speakeasy. It does not depend on Express, Koa, Fastify or any other web framework.

Does it support TypeScript?

Yes. The entire SDK is written in TypeScript and ships type declarations (dist/index.d.ts), providing full autocomplete and type safety for startListener, APIData, ListenerSpecs, ServerConfig and every helper.

Which frameworks does it work with?

The server is framework-free, so it works with any frontend or client: React, Vue, Angular, Svelte, Next.js, React Native, plain fetch, curl and more. Use it as the backend and call it over HTTP.

Do I need Express to use it?

No. Express is not required and is not a dependency. Routing, CORS, JSON parsing and request hardening are all handled by the SDK on top of node:http.

Which HTTP methods are supported?

GET and POST are supported for routes. The SDK responds automatically to OPTIONS preflight requests and answers other methods with 204 No Content.

How do I enable CORS?

Pass allowedOrigins to startListener. Matching origins receive Access-Control-Allow-Origin; OPTIONS responses are handled automatically.

How do I prevent oversized uploads and slowloris attacks?

Configure maxBodySizeMB, requestTimeoutMs, headersTimeoutMs, keepAliveTimeoutMs and maxRequestsPerSocket via setServerConfig. Oversized bodies return 413, invalid JSON returns 400, and the timeouts protect against slowloris/slow-body attacks.

How should I deploy it?

Run it behind an HTTPS reverse proxy such as Apache or Nginx that terminates TLS and forwards plain HTTP to the SDK's port. See Deployment behind Apache.

Keywords

REST API server SDK · Node.js API server · TypeScript server framework · framework-free HTTP server · node:http · createServer · no Express · zero framework · API routing · GET and POST routes · CORS · OPTIONS preflight · JSON body parsing · request hardening · slowloris protection · max body size · AES-256-CBC encryption · HMAC · hCaptcha verification · TOTP · one-time passwords · API codes · string sanitisation · input validation · server-side cache · file helpers · disk utilities · outbound HTTP · TypeScript types · tree-shakeable · lightweight backend · DegreeSign.

Change Log

Change Log

License

MIT © DegreeSign

About

DegreeSign Server SDK gives instant express server setup to provide REST API for any project

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages