> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ancestraldev.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript & Node.js License Validation with Avalex

> Validate Avalex licenses in TypeScript or Node.js applications. Includes HWID generation using the os and crypto modules, with full error handling.

This guide demonstrates how to validate an Avalex license from a TypeScript or Node.js application. The example works in any Node.js server process as well as in the main process of an Electron desktop application. It uses only Node's built-in `crypto` and `os` modules for HWID generation, keeping your dependency footprint minimal.

## Installation

If you are running **Node.js 18 or later**, the global `fetch` API is available natively and you do not need any additional packages. For older Node.js versions, install `node-fetch`:

```bash theme={null}
npm install node-fetch
```

<Note>
  If you are targeting Node 18+, remove the `import fetch from "node-fetch"` line from the example below — the global `fetch` is available automatically. The rest of the code is identical.
</Note>

## Full Example

```typescript theme={null}
import fetch from "node-fetch";
import * as crypto from "crypto";
import * as os from "os";

const AVALEX_URL = "http://localhost:8080/licenses/validate";
const PRODUCT_ID = "prod_enterprise_2026";

function generateHWID(): string {
  const raw = `${os.hostname()}-${os.arch()}-${os.cpus()[0].model}`;
  return crypto.createHash("sha256").update(raw).digest("hex").toUpperCase().slice(0, 32);
}

interface ValidationResponse {
  valid: boolean;
  error?: string;
}

export async function checkAvalexLicense(licenseId: string): Promise<boolean> {
  const hwid = generateHWID();
  try {
    const res = await fetch(AVALEX_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ licenseId, productId: PRODUCT_ID, hwid }),
    });
    if (res.status === 429) {
      console.warn("Avalex rate limit hit.");
      return false;
    }
    if (!res.ok) return false;
    const data = (await res.json()) as ValidationResponse;
    return data.valid === true;
  } catch (err) {
    console.error("Network error validating Avalex license:", err);
    return false;
  }
}
```

## Code Walkthrough

**HWID generation (`generateHWID`)**

`generateHWID` concatenates the system hostname, CPU architecture, and the model name of the first CPU into a single string. This combination is stable across reboots but unique enough to distinguish machines in a fleet. The string is then hashed with SHA-256 using Node's built-in `crypto` module, converted to uppercase hex, and sliced to 32 characters.

**`ValidationResponse` interface**

Casting the parsed JSON to `ValidationResponse` gives you type-safe access to the `valid` boolean. The optional `error` field captures any diagnostic message the server may include without causing a runtime error if it is absent.

**Rate-limit and error handling**

The function checks for a `429` status before calling `res.ok`, so you can log a specific warning and fall back to your cached grace period rather than treating it as a generic failure. Any other non-OK status returns `false`, and the `catch` block handles all transport-level errors (DNS failures, timeouts, SSL issues) in the same way.

<Tip>
  In Electron, call `checkAvalexLicense` in the **main process** before calling `new BrowserWindow(...)`. This ensures the renderer never loads until the license has been confirmed, and it keeps your license key and HWID handling out of the renderer's JavaScript context where it would be more easily inspected.
</Tip>
