@contentauth/c2pa-js
    Preparing search index...

    Module @contentauth/c2pa-utilities

    c2pa-utilities

    c2pa-utilities is a home for shared utilities and libraries used by both c2pa-web and c2pa-node. Most clients will get these transitively as a dependency of one of those two packages, but @contentauth/c2pa-utilities is also published standalone for cases where you want to reuse a piece of it directly.

    npm install @contentauth/c2pa-utilities
    

    Complete API documentation is generated from TypeScript source using TypeDoc and published to GitHub Pages.

    Settings is a plain, JSON-serializable object configuring SDK behavior around trust anchors, verification options, and Reader/Builder options.

    Context is a small, immutable wrapper around Settings, and is the recommended way to configure a Reader/Builder. Context objects are passed directly to the call that creates a Reader/Builder instance, so one running SDK instance can freely create many different Reader/Builders, each with its own Context. Context changes do not propagate, since the Context is snapshotted when used to construct a Reader/Builder. Therefore, it can be safely used to construct multiple instances.

    See c2pa-web's README for an example.

    import { Context } from '@contentauth/c2pa-utilities';

    const context = new Context({
    verify: {
    verifyTrust: true
    },
    trust: {
    trustAnchors: 'https://example.com/trust-anchors.pem'
    }
    });

    Each Context holds whatever single Settings object was passed to its constructor and does not handle any merging of settings. To combine more than one Settings source, merge them first with mergeSettings(), then construct a Context from the single, merged result:

    import { Context, mergeSettings } from '@contentauth/c2pa-utilities';

    const base = { verify: { verifyTrust: true } };
    const override = { verify: { verifyAfterSign: true } };

    const context = new Context(mergeSettings(base, override));
    // context.settings is { verify: { verifyTrust: true, verifyAfterSign: true } }

    Settings are passed across the WASM (c2pa-web)/native(c2pa-node) boundary as a JSON string. toJson() resolves any trust-anchor URLs embedded in the settings (fetching and validating them) and serializes the result:

    const contextJson = await context.toJson();
    // '{"verify":{"verify_trust":true},"trust":{"trust_anchors":"-----BEGIN CERTIFICATE-----..."}}'

    This step is asynchronous, and can throw if a trust-anchor URL fails to resolve. Bindings call it once, right after building the base Context, rather than on every Reader/Builder call. Internally, toJson() is a thin wrapper over resolveSettings, below.

    Context is built on a handful of lower-level Settings helpers, which remain available directly for cases that don't need a Context at all:

    import {
    createTrustSettings,
    createVerifySettings,
    mergeSettings,
    resolveSettings
    } from '@contentauth/c2pa-utilities';

    const trustSettings = createTrustSettings({
    trustAnchors: 'https://example.com/anchors.pem'
    });

    const verifySettings = createVerifySettings({
    verifyTrust: true,
    verifyAfterReading: true
    });

    const settings = mergeSettings(trustSettings, verifySettings);

    // Resolves trust-anchor URLs and serializes to the snake_case JSON string the native SDK expects.
    const settingsJson = await resolveSettings(settings);

    resolveSettings is the entry point most direct callers want. It resolves any trust/cawgTrust URL fields (fetching and inlining the PEM content, retrying transient failures), and returns the result as a snake_case JSON string. settings is merged on top of this package's defaults, so resolveSettings always returns a value, even when called with undefined. To combine more than one Settings object first, merge them with mergeSettings() before calling resolveSettings, as above.

    Other exports:

    • createTrustSettings / createCawgTrustSettings / createVerifySettings — construct a Settings fragment for one section.
    • mergeSettings — deep-merge any number of Settings fragments, with later arguments overriding earlier ones. Nested fields are merged rather than overwritten.
    • settingsToJson — serialize a Settings object to its snake_case JSON form without resolving trust-anchor URLs.
    • snakeCaseify — the lower-level camelCase-to-snake_case object converter settingsToJson/resolveSettings use internally.
    • loadSettingsFromUrl — fetch a settings JSON document from a URL, with retry.
    • resolveTrustSettings — resolve just a TrustSettings object's URL fields in place; used internally by resolveSettings.

    fetchWithRetry and fetchWithRetryRaw wrap fetch with exponential backoff, Retry-After handling, and (for fetchWithRetry) a response size cap. The retry mechanism is fixed; however, policy details such as retry count, backoff timing, which statuses/errors are retryable, and the maximum honored Retry-After delay are configurable per call via FetchWithRetryOptions.

    import { fetchWithRetry, fetchWithRetryRaw } from '@contentauth/c2pa-utilities';

    // GET as text, retrying on network errors, 429, and 5xx, capped at 1 MB by default.
    const text = await fetchWithRetry('https://example.com/anchors.pem');

    // For other methods, headers, or bodies, or to handle the response yourself, use fetchWithRetryRaw.
    const response = await fetchWithRetryRaw('https://example.com/upload', {
    method: 'POST',
    body: payload
    });

    Both functions accept an FetchWithRetryOptions object to override the defaults:

    await fetchWithRetry(url, {
    maxRetries: 5,
    initialRetryDelayMs: 500,
    maxRetryDelayMs: 5_000,
    maxRetryAfterMs: 60_000,
    maxResponseBytes: 5 * 1024 * 1024,
    isRetryableStatus: (status) => status === 429 || status >= 500,
    isRetryableError: (error) => true,
    fetch: myFetchImplementation
    });

    An AbortError is never retried, and a malformed URL throws immediately rather than being retried.

    validateAssetSize is the shared size check used by both Reader implementations before reading an asset.

    import { validateAssetSize, AssetTooLargeError, DEFAULT_MAX_SIZE_IN_BYTES } from '@contentauth/c2pa-utilities';

    try {
    validateAssetSize(sizeInBytes, maxSizeInBytes); // pass 0 to use DEFAULT_MAX_SIZE_IN_BYTES
    } catch (e) {
    if (e instanceof AssetTooLargeError) {
    // asset exceeds the resolved limit
    }
    }

    SigningAlg is the lowercase signing algorithm type accepted/produced by the core native library at the signer construction boundary (e.g. Signer.newSigner(cert, key, alg)). It's derived from the PascalCase SigningAlg exported by @contentauth/c2pa-types, which describes the casing used when a manifest's SignatureInfo.alg is serialized.

    Ensure the repo-wide prerequisites are installed:

    See the c2pa-js README for details.

    To build:

    nx build c2pa-utilities
    

    This library uses Vitest, with msw to mock fetch in the settings and fetch-with-retry tests.

    To run the tests:

    nx test c2pa-utilities
    

    Classes

    AssetTooLargeError
    Context

    Interfaces

    BuilderSettings
    FetchWithRetryOptions
    Settings
    TrustSettings
    VerifySettings

    Type Aliases

    SettingsObjectType
    SettingsValue
    SigningAlg

    Variables

    DEFAULT_INITIAL_RETRY_DELAY_MS
    DEFAULT_MAX_RESPONSE_BYTES
    DEFAULT_MAX_RETRIES
    DEFAULT_MAX_RETRY_AFTER_MS
    DEFAULT_MAX_RETRY_DELAY_MS
    DEFAULT_MAX_SIZE_IN_BYTES
    DEFAULT_SETTINGS

    Functions

    createCawgTrustSettings
    createTrustSettings
    createVerifySettings
    defaultIsRetryableStatus
    fetchWithRetry
    fetchWithRetryRaw
    loadSettingsFromUrl
    mergeSettings
    resolveSettings
    resolveTrustSettings
    settingsToJson
    snakeCaseify
    validateAssetSize
    withDefaultSettings