@primeui/license-manager
Offline license verifier for PrimeUI and PrimeUI PRO. Framework-agnostic — no Vue / React / Angular / Lit peer dependencies.
License keys are configured once at app bootstrap into a process-global registry. Every PrimeUI library and PrimeUI PRO component then reads from the same registry — no licenseKey prop on individual components, no second installer to wrap.
App authors
If you use a Prime UI library (PrimeVue, PrimeReact, PrimeNG, PrimeFaces), pass your PrimeUI license token through that library's existing installer as a single string — it forwards it into this registry for you. You don't import this package directly in that case.
// PrimeVue
app.use(PrimeVue, { theme: { ... }, license: 'PrimeUI-Commercial-key...' });
// PrimeReact
<PrimeReactProvider value={{ theme: { ... }, license: 'PrimeUI-Commercial-key...' }}>
// PrimeNG
providePrimeNG({ theme: { ... }, license: 'PrimeUI-Commercial-key...' });A Commercial or OEM PrimeUI license covers every PRO component via the bundle rule, so this single string is enough for most apps.
If you're mixing standalone PRO buys, or using PRO components without a host Prime library, register the keys yourself before any licensed component mounts:
import { registerLicense } from '@primeui/license-manager';
registerLicense({
primeui: 'PrimeUI-Commercial-key...',
texteditor: 'PrimeUI-PRO-TextEditor-key...',
scheduler: 'PrimeUI-PRO-Scheduler-key...'
});Standalone PRO buyers configure the specific PRO key without a primeui key:
registerLicense({ texteditor: 'PrimeUI-PRO-TextEditor-key...' });PrimeUI PRO component authors
Inside your component, call verifyLicense() at mount time and surface a watermark when invalid.
import { verifyLicense } from '@primeui/license-manager';
import { RELEASE_DATE } from './release-date';
onMounted(async () => {
const result = await verifyLicense('texteditor', { releaseDate: RELEASE_DATE });
if (!result.valid) console.warn(`[PrimeUI TextEditor] ${result.message}`);
licenseResult.value = result;
});Verification is async (Ed25519 via WebCrypto). Do it on client mount, not during SSR render — license status is a UI concern, not a server-render concern, and threading async work into SSR is fragile.
Prime library authors (PrimeVue / PrimeReact / PrimeNG integration)
Add license?: string to your installer's config and forward it to registerLicense({ primeui: ... }) from the install hook. The user passes one token; you wire it into the registry.
// Sketch — inside PrimeVue's install hook
import { registerLicense } from '@primeui/license-manager';
export const PrimeVue = {
install(app, options) {
if (options?.license) registerLicense({ primeui: options.license });
// ... rest of PrimeVue setup
}
};For a host-scoped service (rather than the global registry), use createLicenseService directly:
import { createLicenseService } from '@primeui/license-manager';
const service = createLicenseService({ primeui: options.license });
// stash in PrimeVue's own provide/inject so consumers can read it via usePrimeVue().licenseShort names → product identifiers
The keys object accepts these short names:
| Short name | Product identifier | Covers |
|---|---|---|
primeui |
primeui |
PrimeNG / PrimeVue / PrimeReact / PrimeFaces |
texteditor |
primeui-pro:text-editor |
PRO Text Editor |
scheduler |
primeui-pro:scheduler |
PRO Scheduler |
charts |
primeui-pro:charts |
PRO Charts |
diagram |
primeui-pro:diagram |
PRO Diagram |
pdfviewer |
primeui-pro:pdf-viewer |
PRO PDF Viewer |
taskboard |
primeui-pro:task-board |
PRO Task Board |
datagrid |
primeui-pro:datagrid |
PRO DataGrid |
ganttchart |
primeui-pro:gantt-chart |
PRO Gantt |
filemanager |
primeui-pro:file-manager |
PRO File Manager |
The registry first looks up the specific short name. If that key is missing (or returns wrong-product), it falls back to keys.primeui for any PRO component request. The verifier then accepts that token if its tier is 'commercial'. Community PrimeUI tokens never validate PRO requests.
License Tier + Type
Each signed primeui token carries two claims:
tier— the SKU:community(free) orcommercial(paid).type— the usage model:dev(standard) oroem(redistribution).
PRO tokens omit tier and carry type: 'dev' or type: 'oem'.
| Tier | Type | Behavior |
|---|---|---|
community |
dev |
Free, eligibility-gated. Annual re-confirmation. Time-bound (wall-clock grace). |
commercial |
dev |
Paid perpetual. Library keeps working forever; only versions released after exp blocked. |
commercial |
oem |
Paid annual redistribution license. Time-bound (wall-clock grace). |
Any token with tier === 'commercial' unlocks the PRO bundle rule. Community does not.
Result
interface VerifyResult {
valid: boolean; // true when status is 'active' or 'grace'
status: 'active' | 'grace' | 'expired' | 'invalid' | 'wrong-product' | 'tampered' | 'unconfigured' | 'missing';
daysUntilExpiry?: number;
payload?: LicensePayload;
}| status | meaning |
|---|---|
active |
Verified, not yet expired |
grace |
Expired but within the 30-day grace period — library still works |
expired |
Past the grace period (or version released after exp) — red banner |
wrong-product |
Signed token doesn't cover the requested product |
tampered |
Signature check failed |
invalid |
Malformed token |
missing |
No key configured for this product (and no primeui fallback) |
unconfigured |
registerLicense was never called |
grace is a 30-day window after expiry — library remains functional, caller should surface a warning.
SSR
Module-scoped state is the correct primitive for license keys (build-time config, not request-time). Under SSR:
- The host's installer re-runs per request and calls
registerLicenseagain — idempotent with the same keys. - PRO components defer the
verifyLicensecall to client-side mount (onMounted/useEffect/ngOnInit), not the SSR render pass. No watermark is rendered server-side; it appears after hydration if invalid.
Low-level verify()
If you're verifying a single token without the registry:
import { verify } from '@primeui/license-manager';
const result = await verify(token, { product: 'primeui-pro:scheduler', releaseDate: '2026-04-23' });Keygen (internal, not for consumers)
pnpm --filter @primeui/license-manager keygen
Paste PRIVATE_KEY into the store server env, embed PUBLIC_KEY in src/constants.ts, then publish.