@meyicloud-js/license-agent-client
v1.0.2
Published
Node.js client + Express middleware/router for a local license-agent service (status, activate, license-info, enforcement)
Maintainers
Readme
@meyicloud-js/license-agent-client
Node.js client + Express middleware/router for a local license-agent service.
This package standardizes licensing integration across Node applications by calling a sidecar license-agent that in turn talks to the license-platform:
App (Express/Node) → license-agent → license-platformIt provides:
- Core client (status / limits / activate / license-info)
assertActive()helper (throws when license is inactive)- Express middleware to block product APIs when unlicensed
- Express router exposing
/v1/license/*endpoints used by the activation UI - Built-in activation UI assets (
activate.html,license-gate.js) that apps can use by default or override
Install
npm install @meyicloud-js/license-agent-client
expressis a peer dependency (your app provides it).
Environment variables
| Variable | Default | Description |
|--------|--------|-------------|
| LICENSE_AGENT_URL | http://license-agent:8090 | Base URL of local license-agent |
| LICENSE_CACHE_SECONDS | 30 | Cache TTL (seconds) for status/limits |
| LICENSE_TIMEOUT_SECONDS | 2 | HTTP timeout (seconds) |
| REQUIRE_LICENSE | false | Enable API blocking via middleware |
Core usage (plain Node)
ESM (.mjs / type: module)
import { getClient } from "@meyicloud-js/license-agent-client";
const client = getClient();
const st = await client.status();
console.log(st.active, st.reason);
await client.assertActive(); // throws LicenseInactiveError if inactiveCommonJS
const { getClient } = require("@meyicloud-js/license-agent-client");
(async () => {
const client = getClient();
const st = await client.status();
console.log(st.active, st.reason);
await client.assertActive();
})();Express: block APIs when unlicensed (middleware)
This matches the behavior you used in FastAPI: fail closed.
- Inactive/expired/deactivated → 402
- Agent unreachable → 503 (fail-closed)
ESM default import (recommended)
import express from "express";
import licenseGateMiddleware from "@meyicloud-js/license-agent-client";
const app = express();
app.use(licenseGateMiddleware({
exemptPrefixes: ["/ui", "/health", "/v1/license"], // allow activation UI + license APIs
}));
app.get("/health", (_req, res) => res.json({ ok: true }));
app.get("/api/secure", (_req, res) => res.json({ ok: true }));
app.listen(8080);Named import also works
import express from "express";
import { licenseGateMiddleware } from "@meyicloud-js/license-agent-client";
const app = express();
app.use(licenseGateMiddleware());Express: expose license APIs (activate / info / status)
Mount the router under /v1/license:
import express from "express";
import { createLicenseRouter } from "@meyicloud-js/license-agent-client";
const app = express();
app.use("/v1/license", createLicenseRouter());
app.listen(8080);Routes exposed:
POST /v1/license/activateGET /v1/license/info?license_key=...GET /v1/license/status
Serve the built-in activation UI (optional)
This package ships default UI files:
ui/activate.htmlui/license-gate.js
Mount them with Express:
import express from "express";
import { getBuiltinUiDir } from "@meyicloud-js/license-agent-client";
const app = express();
app.use("/ui", express.static(getBuiltinUiDir()));
// In your app pages, include:
// <script src="/ui/license-gate.js"></script>
app.listen(8080);How the UI works
ui/license-gate.jscallsGET /v1/license/status- If not active, it redirects to
/ui/activate.html?next=... ui/activate.htmluses:GET /v1/license/infoPOST /v1/license/activateGET /v1/license/status
So, for UI to work you must expose the router:
app.use("/v1/license", createLicenseRouter());Override UI logic in an application
If an application needs custom UI or redirect rules, just serve your own /ui directory instead of the built-in one:
app.use("/ui", express.static("/app/my-ui"));Or keep the built-in UI and only override one file by serving a more specific route first.
API reference
LicenseClient methods
status(force?: boolean)→ callsGET /local/statuslimits(force?: boolean)→ callsGET /local/limitsactivate({license_key, product_code, fingerprint?, version?, vm_meta?})→POST /local/activatelicenseInfo(licenseKey)→GET /local/license-info?license_key=...assertActive()→ throwsLicenseInactiveErrorif inactive
Express helpers
licenseGateMiddleware({ exemptPrefixes?, failOpen? })createLicenseRouter({ client?, defaultFingerprint?, defaultVersion? })getBuiltinUiDir()
Common pitfalls
“licenseGateMiddleware is not a function” in ESM
Use either:
- default import:
import licenseGateMiddleware from "@meyicloud-js/license-agent-client"; - or named import:
import { licenseGateMiddleware } from "@meyicloud-js/license-agent-client";
License
MIT
