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

@ondewo/nlu-client-angular

v7.0.1

Published

ONDEWO Natural Language Understanding (NLU) Client library for Angular

Readme

Overview

@ondewo/nlu-client-angular is a compiled version of the ONDEWO NLU API using the ONDEWO PROTO COMPILER. Here you can find the NLU API documentation.

ONDEWO APIs use Protocol Buffers version 3 (proto3) as their Interface Definition Language (IDL) to define the API interface and the structure of the payload messages. The same interface definition is used for gRPC versions of the API in all languages.

Setup

Using NPM:

npm i --save @ondewo/nlu-client-angular

Using GitHub:

git clone https://github.com/ondewo/ondewo-nlu-client-angular.git ## Clone repository
cd ondewo-nlu-client-angular                                      ## Change into repo-directoy
make setup_developer_environment_locally                          ## Install dependencies

Package structure

npm
├── api
│   ├── google
│   │   ├── api
│   │   │   ├── annotations.pb.d.ts
│   │   │   └── http.pb.d.ts
│   │   ├── rpc
│   │   │   └── status.pb.d.ts
│   │   └── type
│   │       └── latlng.pb.d.ts
│   └── ondewo
│       ├── nlu
│       │   ├── agent.pbconf.d.ts
│       │   ├── agent.pb.d.ts
│       │   ├── agent.pbsc.d.ts
│       │   ├── aiservices.pbconf.d.ts
│       │   ├── aiservices.pb.d.ts
│       │   ├── aiservices.pbsc.d.ts
│       │   ├── ...
│       └── qa
│           ├── qa.pbconf.d.ts
│           ├── qa.pb.d.ts
│           └── qa.pbsc.d.ts
├── esm2022
│   ├── api
│   │   ├── google
│   │   │   ├── api
│   │   │   │   ├── annotations.pb.mjs
│   │   │   │   └── http.pb.mjs
│   │   │   ├── rpc
│   │   │   │   └── status.pb.mjs
│   │   │   └── type
│   │   │       └── latlng.pb.mjs
│   │   └── ondewo
│   │       ├── nlu
│   │       │   ├── agent.pbconf.mjs
│   │       │   ├── agent.pb.mjs
│   │       │   ├── agent.pbsc.mjs
│   │       │   ├── ...
│   │       └── qa
│   │           ├── qa.pbconf.mjs
│   │           ├── qa.pb.mjs
│   │           └── qa.pbsc.mjs
│   ├── ondewo-nlu-client-angular.mjs
│   └── public-api.mjs
├── fesm2022
│   ├── ondewo-nlu-client-angular.mjs
│   └── ondewo-nlu-client-angular.mjs.map
├── index.d.ts
├── LICENSE.MD
├── package.json
├── public-api.d.ts
└── README.md

Authentication (Keycloak bearer token)

The hand-written auth surface lives in src/auth/ and attaches the current Keycloak access token as an Authorization: Bearer <token> credential to every outgoing gRPC-web and HTTP request. It is exported from the package entry point, so consumers never re-implement token acquisition or refresh.

There are two ways to feed it a token; pick the one that matches the account type.

Technical users — let this library log in and refresh

A technical user is a service account with 2FA disabled, so the Resource Owner Password Credentials grant is usable. KeycloakTokenProvider performs that login once against the public SDK client, then refreshes the access token in the background REFRESH_SKEW_IN_S (30s) before it expires, for as long as the application lives. Nothing else has to run a timer.

import { bootstrapApplication } from "@angular/platform-browser";
import { provideHttpClient, withInterceptors } from "@angular/common/http";
import {
  authHttpInterceptor,
  KEYCLOAK_TOKEN_PROVIDER_CONFIG,
  KeycloakTokenProvider,
  provideOndewoNluAuth
} from "@ondewo/nlu-client-angular";

bootstrapApplication(AppComponent, {
  providers: [
    {
      provide: KEYCLOAK_TOKEN_PROVIDER_CONFIG,
      useValue: {
        keycloakUrl: "https://keycloak.example.com",
        realm: "ondewo",
        clientId: "ondewo-nlu-cai-sdk-public",
        username: "technical-user",
        password: "..."
      }
    },
    provideOndewoNluAuth(KeycloakTokenProvider),
    provideHttpClient(withInterceptors([authHttpInterceptor]))
  ]
});

A long-lived offlineToken can be supplied instead of username + password; tokenExpirationInS bounds the refresh loop when the session must not outlive a fixed window. The Keycloak client must have direct access grants and the offline_access scope enabled, otherwise the token response carries no refresh token and KeycloakTokenProvider reports a KeycloakAuthenticationError.

The password grant is deliberately limited to technical users: for a human account with 2FA enabled it cannot work, and sending a human's password to the token endpoint from the browser is not acceptable.

Credentials that are only known at runtime

An embedded widget usually learns its technical user from its own URL, long after the application has bootstrapped, so there is nothing to put in KEYCLOAK_TOKEN_PROVIDER_CONFIG at startup. In that case register the provider without a config and call configure() once the credentials are known:

await tokenProvider.configure({
  keycloakUrl: issuerFromQueryParams,
  realm: "ondewo-ccai-platform",
  clientId: "ondewo-nlu-cai-sdk-public",
  username: techUserFromQueryParams,
  password: techSecretFromQueryParams
});

Registered without a config the provider stays idle — it issues no request and getToken() returns null — until configure() is called. Calling configure() again re-points the provider at different credentials: the pending refresh is cancelled and the cached tokens are dropped before the new login runs, so no stale bearer can be served in between and the provider need not be re-created.

Renewing on demand

The background timer keeps the token fresh on its own, but a transport that must never send a dead bearer — and must recover when the server rejects one — can drive the renewal directly:

// Pre-flight: renews only if the token has lapsed or is within REFRESH_SKEW_IN_S of doing so.
const bearer = await tokenProvider.ensureFreshToken();

// Recovery: after the server answered UNAUTHENTICATED, renew unconditionally and replay once.
const renewed = await tokenProvider.ensureFreshToken({ force: true });

force matters because a cached expiry cannot be trusted after a rejection — the token may have been revoked, or the local clock may run ahead of Keycloak's. Concurrent calls are single-flighted, so a burst of requests arriving on an expired token issues one grant rather than one per request. If the refresh token itself has been revoked, ensureFreshToken falls back to a full re-login with the configured credentials; it returns null when the provider has no config yet.

Interactive users — supply the token from the host application

When a real person logs in (2FA, authorization-code flow), the host application owns the OIDC session and only hands the current token over through a TokenProvider:

import { Injectable } from "@angular/core";
import Keycloak from "keycloak-js";
import { TokenProvider, TokenResult } from "@ondewo/nlu-client-angular";

@Injectable({ providedIn: "root" })
export class HostSessionTokenProvider implements TokenProvider {
  constructor(private readonly keycloak: Keycloak) {}

  // Refresh the token if it expires within 30s, then return the current one.
  // Returning a Promise lets the interceptor await the refresh before sending.
  getToken(): TokenResult {
    return this.keycloak
      .updateToken(30)
      .then(() => this.keycloak.token ?? null)
      .catch(() => null);
  }
}

Register it the same way: provideOndewoNluAuth(HostSessionTokenProvider).

getToken() may return a string, null (unauthenticated — the request is sent without an Authorization header), a Promise<string | null>, or an Observable<string | null>. With keycloak-angular you would instead inject KeycloakService and call this.keycloakService.getToken().

What the registration does

provideOndewoNluAuth binds TOKEN_PROVIDER to your implementation and registers the @ngx-grpc AuthGrpcInterceptor for all generated *.pbsc.ts clients. Adding authHttpInterceptor covers plain HTTP requests. Every request then carries authorization: Bearer <token> whenever a token is available, and is sent unchanged when it is not.