npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uipath/du-utils

v1.0.0-rc.2

Published

Framework-agnostic loaders and TypeScript contracts for embedding the UiPath Document Understanding web components (Validation Station and Classification Station).

Readme

@uipath/du-utils

Framework-agnostic utilities for embedding the UiPath Document Understanding web components — Validation Station and Classification Station — in any web application.

This package lets a host application load a DU web component from a deployment URL you control (a path or origin you host the built assets on) and interact with it through strongly-typed custom elements. It has no Angular/React dependency and works in plain HTML, React, Angular, or any other framework.

What's in the box

  • loadValidationStationWebComponent / loadClassificationStationWebComponent — load a web component's assets from a deployment URL and register its custom element.
  • TypeScript contracts for the registered custom elements — element interfaces, event maps, and ambient HTMLElementTagNameMap / JSX augmentations so querySelector, viewChild, and JSX all return the right types.
  • Shadow-DOM styling helpers used by the components' own bootstrap (advanced).
import {
    loadValidationStationWebComponent,
    loadClassificationStationWebComponent,
    type IValidationStationWcElement,
    type IValidationStationWcEventMap,
} from '@uipath/du-utils';

Install

# npm
npm install @uipath/du-utils

# yarn
yarn add @uipath/du-utils

# pnpm
pnpm add @uipath/du-utils

The only runtime dependency is @uipath/uipath-typescript (the DU SDK types the Validation Station contract is built on).

Loading a web component

Point the loader at the URL where the web component's build artifacts are served. It injects the component's <script type="module"> files (polyfills.js, then main.js) and a <link> to cache-warm the theme (styles.css), then resolves once the component's custom element is registered.

import { loadValidationStationWebComponent } from '@uipath/du-utils';

await loadValidationStationWebComponent(document, 'https://assets.example.com/du-vs-wc/latest');

// The custom element is now registered — create it and set its inputs.
const el = document.createElement('ui-du-validation-station-wc-element');
el.theme = 'light';
el.language = 'en';
el.platform = { organizationName: 'acme', tenantId: 't1' };
document.body.appendChild(el);

The deployment URL is the directory that serves the component's assets:

https://assets.example.com/du-vs-wc/latest/
├── main.js
├── polyfills.js
├── styles.css     (theme — preloaded, adopted into the shadow root)
├── fonts.css      (opt-in — see `includeFonts`)
├── media/         (the font binaries fonts.css references)
└── du-assets/     (runtime assets: pdf.js, translations, business-rules executor)

Deploy the component build's entire output at this URL, not just the top-level files. media/ and du-assets/ are directories the component fetches at runtime; if they are missing, the failures surface in the browser with nothing reported at build time.

Validation Station assets are produced by the @uipath/du-validation-station-wc build; Classification Station assets by the corresponding Classification Station web-component build. A UiPath-hosted deployment serves the full fonts.css (Apollo text fonts + Material Icons). Those npm packages are built differently — their fonts.css carries Material Icons only — so a base you assemble by copying files out of one of them still serves includeFonts correctly, it just supplies the icons rather than the whole Apollo set.

Options

await loadValidationStationWebComponent(document, deploymentUrl, { includeFonts: true });

| Option | Default | Description | |---|---|---| | includeFonts | false | Inject a light-DOM <link rel="stylesheet"> to the component's fonts.css. Requires both fonts.css and the sibling media/ directory it references to be served at the deployment URL. What you get depends on how that base was built: a UiPath-hosted deployment serves Apollo text fonts + Material Icons, while a base assembled from the component's npm package serves Material Icons only. Leave it false when the host already loads Apollo globally (e.g. Action Center, DU Center) to avoid double-loading. |

With includeFonts: false the loader injects no fonts at all — including the icon font. That is correct for hosts that already load Apollo globally (Action Center, DU Center), because Apollo's font.css contains Material Icons. A host that loads neither will render every icon as its ligature text (menu, close, …) — set includeFonts: true, or link the deployment's fonts.css yourself.

Idempotency & caching

Each component is loaded once per page: the load promise is cached on window per component, so calling the loader again returns the same promise without re-injecting scripts. A later call with { includeFonts: true } still injects the fonts stylesheet against the already-resolved base, so opting into fonts after an initial load works.

Trailing slashes on the deployment URL are normalized, so .../latest and .../latest/ behave identically.

Typed custom elements

Once a component is loaded, its custom element is available with full type support. The HTMLElementTagNameMap and React.JSX.IntrinsicElements augmentations are ambient — they apply as soon as the package is referenced, so querySelector / viewChild / JSX return the typed element with no cast.

| Element tag | Interface | |---|---| | <ui-du-validation-station-wc-element> | IValidationStationWcElement | | <ui-du-validation-station-wc-persistent-element> | IPersistentValidationStationWcElement | | <ui-du-classification-station-wc-element> | IClassificationStationWcElement |

The standalone element variants ship their own type declarations in @uipath/du-validation-station-wc — see that package for typed consumption of those.

React

import { useEffect, useRef } from 'react';
import {
    loadValidationStationWebComponent,
    type IValidationStationWcElement,
    type IValidationStationWcEventMap,
} from '@uipath/du-utils';

function ValidationStation({ deploymentUrl }: { deploymentUrl: string }) {
    const ref = useRef<IValidationStationWcElement | null>(null);

    useEffect(() => {
        void loadValidationStationWebComponent(document, deploymentUrl);
    }, [deploymentUrl]);

    useEffect(() => {
        const el = ref.current;
        if (!el) return;

        el.platform = { organizationName: 'acme', tenantId: 't1' };

        // addEventListener overloads give a typed `event.detail`.
        const onSaveResult = (e: CustomEvent<IValidationStationWcEventMap['saveResult']>) =>
            console.log('saved ok?', e.detail.success);

        el.addEventListener('saveResult', onSaveResult);
        return () => el.removeEventListener('saveResult', onSaveResult);
    }, []);

    // React 19: pass inputs directly as JSX props (augmentation is automatic).
    return <ui-du-validation-station-wc-element ref={ref} theme="light" language="en" />;
}

Angular

Angular passes inputs as element properties and listens to outputs as DOM events via (eventName) binding. The HTMLElementTagNameMap augmentation makes viewChild / querySelector return the typed element.

import { Component, viewChild } from '@angular/core';
import {
    loadValidationStationWebComponent,
    type IValidationStationWcElement,
    type IValidationStationWcEventMap,
} from '@uipath/du-utils';

@Component({
    template: `
        <ui-du-validation-station-wc-element
            #vsWc
            [theme]="theme"
            [platform]="platform"
            (saveResult)="onSaveResult($event)"
        />
    `,
})
export class ValidationStationComponent {
    readonly vsWc = viewChild.required<IValidationStationWcElement>('vsWc');

    constructor() {
        void loadValidationStationWebComponent(document, this.deploymentUrl);
    }

    onSaveResult(e: CustomEvent<IValidationStationWcEventMap['saveResult']>): void {
        console.log('save ok?', e.detail.success);
    }
}

The event maps (IValidationStationWcEventMap, IClassificationStationWcEventMap) map every event name to the type carried in CustomEvent.detail — e.g. loaded: boolean, fieldValueChanged: IFieldValueDetailsDto, saveResult: ISaveResult, actionCenterTaskComplete: number. Import the detail types you need directly from this package.