Client integration

Integrate Hiphops product keys into your applications using the Hook client libraries for license validation.

Hook client library

The @hiphops/hook client library provides a simple interface for license validation in JavaScript/TypeScript applications.

📖 View on GitHub

Installation

npm install @hiphops/hook

Basic usage

import { license } from '@hiphops/hook';

const getLicenseInfo = async () => {
  try {
    const info = await license();
    if (info.verified) {
      console.log('License is valid:', info.license);

      // Access specific license fields
      const maxSeats = info.license.seats;

      console.log(`License valid for ${maxSeats} users`);
    } else {
      console.warn('License verification failed:', info.verify_failures);
      // Your app should decide what to do here - typically exit or disable features
      process.exit(1);
    }
    return info;
  } catch (error) {
    console.error('Error getting license info:', error);
    // Handle missing LICENSE_TOKEN or other errors
    process.exit(1);
  }
};

License response structure

Valid license:

{
  "verified": true,
  "verify_failures": [],
  "license": {
    "seats": 10
  },
  "hiphops": {
    "identity": "c_01jz3b9bz4ka7stedds7g3fjb7",
    "project_id": "my-project-1234"
  }
}

Invalid license:

{
  "verified": false,
  "verify_failures": ["invalid_license_token"],
  "license": null,
  "hiphops": {
    "identity": "",
    "project_id": ""
  }
}

Setting up the license token

Hook reads the license token from the LICENSE_TOKEN environment variable.

Local development

export LICENSE_TOKEN="your_jwt_token_here"
node your-app.js

Docker

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm run build

# Set the license token
ENV LICENSE_TOKEN=""

CMD ["npm", "start"]

Docker Compose

version: '3.8'
services:
  app:
    build: .
    environment:
      - LICENSE_TOKEN=${LICENSE_TOKEN}
    ports:
      - '3000:3000'

Express.js integration

import { license } from '@hiphops/hook';
import express from 'express';

const app = express();

// License validation middleware
const validateLicense = async (req, res, next) => {
  try {
    const licenseInfo = await license();
    if (!licenseInfo.verified) {
      return res.status(403).json({
        error: 'Invalid license',
        failures: licenseInfo.verify_failures,
      });
    }
    req.license = licenseInfo.license;
    next();
  } catch (error) {
    res.status(500).json({ error: 'License validation failed' });
  }
};

// Protected route
app.get('/api/protected', validateLicense, (req, res) => {
  res.json({
    message: 'Access granted',
    license: req.license,
  });
});

Feature gating

Use license fields to control application features:

const checkFeatureAccess = async (feature) => {
  const licenseInfo = await license();

  if (!licenseInfo.verified) {
    return { allowed: false, reason: 'Invalid license' };
  }

  const config = licenseInfo.license;

  switch (feature) {
    case 'premium_features':
      return {
        allowed: config.tier === 'premium',
        reason: config.tier !== 'premium' ? 'Premium tier required' : null,
      };

    case 'user_limit':
      const currentUsers = getCurrentUserCount();
      return {
        allowed: currentUsers < config.seats,
        reason: currentUsers >= config.seats ? 'User limit exceeded' : null,
      };

    default:
      return { allowed: true };
  }
};

Registry authentication

Product keys also provide Docker registry access. Customers can use their JWT token as Docker credentials:

docker login your-project.ctr.dev -u customer -p <jwt-token>
docker pull your-project.ctr.dev/your-image:latest

Error handling

Common failure scenarios

Missing license token:

// Hook will fail if LICENSE_TOKEN is not set
try {
  const info = await license();
} catch (error) {
  console.error('License check failed:', error.message);
  // Handle gracefully - exit, show error, or disable features
}

Invalid or expired token:

const info = await license();
if (!info.verified) {
  info.verify_failures.forEach((failure) => {
    switch (failure) {
      case 'invalid_license_token':
        console.error('License token is invalid');
        break;
      case 'token_expired':
        console.error('License token has expired');
        break;
      default:
        console.error('License verification failed:', failure);
    }
  });
}

Handling license validation failures

Important: Your application must decide what to do when license validation fails. Common approaches include:

const info = await license();

if (!info.verified) {
  // Option 1: Exit the application
  console.error('Invalid license - application cannot start');
  process.exit(1);

  // Option 2: Disable premium features
  enablePremiumFeatures = false;

  // Option 3: Show error and continue in limited mode
  showLicenseError('License validation failed');
  enableLimitedMode = true;
}

Accessing license fields

License fields contain custom data defined in your product configuration:

const info = await license();
if (info.verified) {
  // Access any custom field defined in your product
  const seats = info.license.seats; // Number field
  const expires = info.license.expires_at; // Date field

  // Use fields to control application behavior
  if (getCurrentUserCount() > seats) {
    throw new Error(`User limit exceeded. Licensed for ${seats} users.`);
  }
}

Custom binary path

Hook automatically manages the license validation binary, but you can specify a custom path:

export HIPHOPS_HOOK_BIN=/path/to/custom/hook-binary

Platform support

The Hook client works on:

  • Node.js (16+)
  • Deno (via npm compatibility)
  • Bun
  • Docker containers (Linux, macOS, Windows)