Atomic Angular — Doc interne

Provide a client

Give an application its own Sinequa client — its own configuration, session and event subscribers — instead of the default one backing the free functions.

Every store, service and component in this library reaches the Sinequa backend through one client, resolved from the ATOMIC_CLIENT injection token. provideAtomicClient() is how an application gives that token its own client instead of the default one.

Concept — the default client

ATOMIC_CLIENT defaults to the client backing @sinequa/atomic's free functions (login(), fetchQuery(), …), whose configuration is globalConfig. An application that never calls provideAtomicClient() behaves exactly as before — there is nothing to migrate.

Minimal example

An isolated client at the application root
app.config.ts
import { ApplicationConfig, provideAppInitializer } from "@angular/core";
import { bootstrapApp, provideAtomicClient } from "@sinequa/atomic-angular";

export const appConfig: ApplicationConfig = {
  providers: [
    // backendUrl may be omitted — bootstrapApp derives it from the browser URL.
    provideAtomicClient({ app: "my-app" }),
    provideAppInitializer(() => bootstrapApp({ createRoutes: true })),
  ],
};

How it works

provideAtomicClient(config) registers a factory for ATOMIC_CLIENT that calls createAtomicClient(config) from @sinequa/atomic — one client, one configuration, one session, one set of event subscribers, isolated from whatever the default client is doing. injectAtomicClient() is inject(ATOMIC_CLIENT) under a clearer name.

provideAtomicClient(config) provideAtomicClient(config2) — shadows the token injectAtomicClient() injectAtomicClient() Application root ATOMIC_CLIENT A route/component subtree ATOMIC_CLIENT (subtree) Stores, services, components Same stores/services, in that subtree

Registering provideAtomicClient() again in a route or component injector shadows the token for that subtree only — which is how a second backend is served (see Serve a second backend). Providing the client alone is rarely what a subtree serving a second backend wants, though: the library's stores and services stay bound to whichever client was in scope when they were first constructed — use provideAtomicScope() for a self-contained subtree.

Recipes

Configuration known only at start-up

Pass a function instead of an object when part of the configuration is resolved after this module is evaluated — an SPFx web part supplying backendUrl at runtime, say. The object form is captured when the providers are declared; the function form runs when the injector actually builds the client.

Configuration resolved at runtime
app.config.ts
provideAtomicClient(() => ({ ...environment, ...hostOverrides() }))

Reading the client and checking the session without redirecting

login() is not a question — for oauth/saml it navigates away to the identity provider. Ask hasSession() instead to decide what to render.

Deciding what to render
sample.component.ts
import { Component, inject } from "@angular/core";
import { injectAtomicClient } from "@sinequa/atomic-angular";

@Component({ selector: "sample-component", template: `` })
export class SampleComponent {
  private readonly client = injectAtomicClient(); // or inject(ATOMIC_CLIENT)

  protected readonly isCredentialsMode = this.client.config.authMode?.kind === "credentials";

  async checkSession() {
    // Answers from the stored token when there is one, asks the server otherwise —
    // never redirects, never throws.
    return this.client.auth.hasSession();
  }
}

client.auth.isRedirectPending() tells a provider handshake apart from a plain missing session. client.storagePrefix reads back the prefix namespacing this client's storage keys.

Options

Prop

Type

Pitfalls

What's next

On this page