Web SDKv1.0.0

Kernstra

The SDK entry point: all members are static. Kernstra.init() verifies the license and loads the engine binary; call it once, before creating any viewer, and await it before PDFDocument.fromUrl(), fromFile(), fromBytes() or fromUrlProgressive() — all four require the engine to be loaded.

A valid license, development or production, is required: without one init() shows a "License required" popup, rejects with LICENSE_REQUIRED and never downloads the engine. Pass the token to init, typically from your build's own variable, or set it where the SDK looks when none is passed: a globalThis.KERNSTRA_LICENSE string, a <meta name="kernstra-license" content="…"> tag, or, in Node, process.env.KERNSTRA_LICENSE. The SDK ships prebuilt, so a bundler cannot substitute an environment variable into it; read the variable in your code. The license chapter (Licensing) covers origins, the secure-context rule, the status check, outages and which feature each tool and API member needs.

static classKernstra

Usage

TypeScript
import { Kernstra, PDFDocument } from '@kernstra/pdf-web-sdk';

// Application startup (once)
await Kernstra.init({ license: import.meta.env.KERNSTRA_LICENSE });

// Then load documents as needed
const doc = await PDFDocument.fromUrl('/my-file.pdf');

Lifecycle

initstatic methodsince 1.0.0
static init(options?: SDKInitOptions): Promise<void>

Initialize the SDK — verifies the license and loads the engine binary. Call before creating any viewer; resolves when the engine is ready.

Idempotent: a second call with the same options gets the same promise (React's StrictMode needs no guard), one with other options rejects with INVALID_ARGUMENT, and a failed call starts over on the next. An empty or missing license means "no license given"; only setLicense('') signs out and forgets the cached token.

The token is verified locally in milliseconds; its status is confirmed with the licensing API once per load. A load that holds a recent good answer never waits; a load without one (the first on a browser, site data cleared, a frame without storage, an answer older than 48 hours, or a paused license) waits for the check, at most 8 seconds. Nothing runs that we did not publish: the engine, the shaping and subsetting binaries and every bundled font are downloaded from the asset store your license names, by digest, verified and cached in the browser.

ParameterTypeDescription
options?SDKInitOptionslicense (your license token), engineUrl, shaperUrl and subsetterUrl (self-hosted copies of the binaries — self-hosting licenses only), workerUrl (the render worker), styleNonce (the page's CSP nonce, carried by every stylesheet the SDK injects) and licensePopup (the "License required" popup in your own words). See Initialization.
Returns Promise<void> Resolves when the engine is ready.
  • LICENSE_REQUIRED — no valid license, or not a secure context (the SDK runs only over HTTPS or on localhost; on a plain-HTTP origin it refuses to start with reason insecure-context).
  • FEATURE_NOT_LICENSED — engineUrl, shaperUrl or subsetterUrl given without a self-hosting license.
  • ENGINE_LOAD_FAILED — the binary was not downloaded, not verified, or not started.
  • INVALID_ARGUMENT — a second call with other options, a styleNonce that is not base64 or base64url, or a licensePopup part that is not a string.
  • INVALID_STATE — called outside a browser, where there is no window or document: server rendering.
TypeScript
await Kernstra.init({ license: import.meta.env.KERNSTRA_LICENSE });
isInitializedstatic methodsince 1.0.0
static isInitialized(): boolean
Returns true if the SDK has been initialized.
Returns boolean
TypeScript
if (!Kernstra.isInitialized()) {
  await Kernstra.init({ license: import.meta.env.KERNSTRA_LICENSE });
}
destroystatic methodsince 1.0.0
static destroy(): void

Tear down the SDK and free its resources. Destroy your viewers and close your documents first (each viewer terminates its render worker): with a document still open it throws INVALID_STATE rather than free them from under it.

After an ENGINE_FAILED fault it tears down whatever is open — that is the recovery — and a document closed after it is already released, so its close() does nothing. destroy() removes the onLicenseChange subscriptions, like every other SDK listener; Kernstra.events subscriptions are kept across it.

Returns void
  • INVALID_STATE — a document is still open.
TypeScript
viewer.destroy();
await doc.close();
Kernstra.destroy();
versionstatic propertysince 1.0.0
static get version(): string
SDK version string, matching the published package.
Returns string
TypeScript
console.log('Kernstra Web SDK', Kernstra.version);

License

setLicensestatic methodsince 1.0.0
static setLicense(token: string): Promise<LicenseState>

Replaces the license at runtime; resolves to the new license state. A setLicense is a load: the licensing API confirms the token's status, and a license that does not load (revoked, paused, expired, a copied token, a host it does not name, a malformed or forged key) shows the "license required" popup — signing out with '' stops nothing that is open. Presenting the same key again changes neither a pause nor a revocation.

A verdict that adds rights reaches open documents at once; a viewer whose document's rights grow rebuilds its toolbar. A verdict that takes rights away reaches only the next load: each document keeps the rights it was opened with until it is closed.

ParameterTypeDescription
tokenstringThe new license token. '' signs out: it forgets the cached token, but not a stop — only a license that loads lifts a pause or a revocation.
Returns Promise<LicenseState> Resolves to the new license state.
TypeScript
const state = await Kernstra.setLicense(newToken);
if (state.valid && state.features.includes('export')) enableDownload();
getLicensestatic methodsince 1.0.0
static getLicense(): LicenseState

The current license state, as the exported LicenseState. if (state.valid) state.features.includes('export') type-checks: the valid half has every field, the invalid half the reason.

An invalid state's reason is one of no-license, insecure-context (plain HTTP), malformed, unsupported-algorithm, invalid-signature, not-yet-valid, expired, origin-mismatch, wrong-holder, revoked, paused or stale (the licensing API has not confirmed the license for more than 48 hours, or never on this browser and the check could not get through; the SDK loads, watermarked and without extract, and asks again whenever a document is opened). A paused state carries pauseReason: payment, suspended, term_ended, trial_ended or other. During a licensing-API outage getLicense() says why output is watermarked. It reports a verdict as soon as it arrives; documents already open keep the rights they were opened with.

Returns LicenseState A union narrowed on valid: the valid half carries watermark, env, plan, features, offline and, on a license with an expiry date, expiresAt; the invalid half carries watermark: true, a reason and, when the reason is paused, a pauseReason.
TypeScript
const state = Kernstra.getLicense();
if (!state.valid) console.warn('License not valid:', state.reason);
else if (state.watermark) console.warn('Output is watermarked (development token)');
onLicenseChangestatic methodsince 1.0.0
static onLicenseChange(callback: (state: LicenseState) => void): () => void

Calls callback with each new license state; returns a function that unsubscribes. The same changes arrive as the licenseChanged event on Kernstra.events. A verdict that takes rights away — revoked, paused, fewer features, the outage grace period run out — is reported at once here but reaches only the next load (init, setLicense, or opening a document): whoever is exporting, printing or filling a form in an open document finishes. Listen here if your app should react sooner.

Kernstra.destroy() removes these subscriptions; one made before an init() refused for want of a license stays, so it sees the retry.

ParameterTypeDescription
callback(state: LicenseState) => voidCalled with each new license state.
Returns () => void A function that unsubscribes.
TypeScript
const stop = Kernstra.onLicenseChange((state) => {
  if (!state.valid) showBanner('License problem: ' + state.reason);
});
// later
stop();

Events and assets

eventsstatic propertysince 1.0.0
static get events(): GlobalEvents
Global GlobalEvents — on() and off() for GlobalEventMap; see the Event System. Only the SDK emits on it. Kept across destroy(): subscribe once, at module level if you like.
Returns GlobalEvents on() and off() for GlobalEventMap.
TypeScript
Kernstra.events.on('licenseChanged', (state) => {
  console.log('license', state.valid ? state.plan : state.reason);
});
assetDigestsstatic propertysince 1.0.0
static readonly assetDigests: Readonly<{ engine: string; shaper: string; subset: string; fonts: Readonly<Record<string, string>> }>
The SHA-256 of every file this version downloads: { engine, shaper, subset, fonts }, fonts keyed by font id (BUILTIN_FONTS[i].id), for scripting a self-hosted deployment; the subset digest's folder in the store is subsetter. See Engine, binaries and fonts.
Returns { engine, shaper, subset, fonts }
TypeScript
const { engine, shaper, subset, fonts } = Kernstra.assetDigests;
console.log(engine, Object.keys(fonts).length, 'fonts');