Migrating from 1.x
The one breaking change between 1.x and 2.x, the type changes that surface as compile errors, and what is worth rewriting even though it still runs.
The jump from 1.1.4 to 2.0.0 had a single breaking change. The rest of what you will notice is either a type
becoming honest — which turns a latent runtime failure into a compile error — or a new way of writing something
that already worked.
Replace the three auth booleans with authMode
The one real break. useCredentials, useSSO and useSAML were three overlapping booleans; they are now
read-only getters derived from a single discriminated union.
// 1.x
setGlobalConfig({ useCredentials: true });
setGlobalConfig({ useSSO: true });
setGlobalConfig({ useSAML: true, autoSAMLProvider: "okta" });
// 2.x
import { AuthMode } from "@sinequa/atomic";
setGlobalConfig({ authMode: AuthMode.credentials() });
setGlobalConfig({ authMode: AuthMode.sso() });
setGlobalConfig({ authMode: AuthMode.saml("okta") });
setGlobalConfig({ authMode: AuthMode.oauth("azure-ad") });
setGlobalConfig({ authMode: AuthMode.bearer(token) });// 1.x
setGlobalConfig({ useSSO: true, backendUrl: environment.backendUrl });
// 2.x — on a client, which is what the rest of this documentation uses
import { AuthMode, createAtomicClient } from "@sinequa/atomic";
const client = createAtomicClient({
app: environment.app,
backendUrl: environment.backendUrl,
authMode: AuthMode.sso(),
});// 1.x
setGlobalConfig({ useCredentials: true, backendUrl: import.meta.env.VITE_BACKEND });
// 2.x
import { AuthMode, createAtomicClient } from "@sinequa/atomic";
export const sinequa = createAtomicClient({
app: import.meta.env.VITE_APP,
backendUrl: import.meta.env.VITE_BACKEND,
authMode: AuthMode.credentials(),
});Writes still work, translated: setGlobalConfig({ useSSO: true }) sets authMode for you, and an explicit
authMode always wins over a boolean in the same call. Reads still work too — they are getters. So nothing
breaks at runtime; what breaks is any code that assigned one of them directly on globalConfig, since a
getter has no setter.
Two behaviours changed with the rewrite, and both are improvements you should know about:
- The
unknownmode now really does "try SSO, then fall back to credentials". In 1.x that resolution block was dead code. On fallback it setsauthMode = credentials, so a sign-in screen renders deterministically. initializeAppConfig()resolves the mode from the server's pre-login response when your configuration declares none. See Automatic detection.
Fix the compile errors the honest types produce
Nothing was removed here — three types stopped over-promising. Each error was a bug already.
| The change | The error you get | What to do |
|---|---|---|
Result.queryIntents is now optional | possibly 'undefined' | Guard it. The server omits the key unless the query carries a query-intent configuration, so you were reading undefined while the type promised an array |
AggregateResult exists | Assigning an aggregate response to Result | An action: "aggregate" query answers four fields, not sixteen. Type those responses AggregateResult — Reading a result |
logout() declares Promise<string | undefined> | An unused-value or unhandled-type warning | It returns the provider's logoutUrl when the server gave one. Navigate to it, or ignore it explicitly |
One silent behaviour change with no compile error, worth checking by hand: fetchQuery and fetchBulkQuery no
longer compute nextPage / previousPage from fields the response does not carry. Math.ceil(undefined / undefined) is NaN, and every comparison against NaN is false — so in 1.x a response with no pagination
read exactly like one on its last page. Both are now undefined explicitly. A pager that tested
nextPage > page needs to test for undefined instead.
Set uiLanguage if you localise
The locale sent in every request body used to be body.locale || navigator.language, so the browser had
the last word: an interface switched to English still asked the server in fr-FR, and the server localised
accordingly. It is now body.locale || uiLanguage || navigator.language.
If your application switched language through its own mechanism and relied on the browser locale reaching the
server, set uiLanguage explicitly — Localisation.
Rename what was renamed
Aliases, all still exported, all @deprecated. A find-and-replace, and your editor already flags them.
| 1.x | 2.x |
|---|---|
getJWToken | requestWebTokenSession |
appInitializerFn | initializeAppConfig |
fetchSuggestQuery | fetchSuggest |
PrincipalChangedEvent | PrincipalEvent |
ExportQuery | ExportQueryModel |
initializeAadHttpClient (global) | createSpfxHttpAdapter(aadHttpClient) from @sinequa/atomic/spfx |
Consider a client instead of globalConfig
Not required — the free functions run on a default client whose configuration is globalConfig, read live,
and getDefaultClient() hands you that same instance. Both APIs are two views of one state and work side by
side.
Worth doing when any of the following applies:
- Two backends, or two apps on one backend. Impossible with process-wide state. Give each client a distinct
storagePrefixor they overwrite each other's token — Several backends. - Tests. A client takes its
fetch,storageandloggeras configuration, so no module mocking and no leakage between test files — Testing. - SharePoint.
createSpfxHttpAdapter(aadHttpClient)replaces theinitializeAadHttpClientglobal — SPFx.
The client covers the trade-off, including the @experimental tag it carries.
Adopt what 2.x added, where it removes code you wrote
Each of these existed in some form in every application built on 1.x, usually written by hand.
onAuthEvent / client.auth.on
A typed lifecycle channel — authenticated, unauthorized, requestFailed, tokenRefreshed,
loggedOut — that works without a DOM, unlike the authenticated CustomEvent it replaces.
recoverFromUnauthorized
Repair the session on a 401 and the request is replayed once. Concurrent 401s share a single call.
isExternalAuthMode
Whether a mode needs a password form. The set every application enumerated by hand, and the member
everyone forgot was bearer — which showed a password prompt for an authentication that has none.
filter.distribution
Filtering on a date or size bucket. Passing such an item's value to filter.eq earns a 500; this
parsing used to live only inside the Angular companion package.
hasSession
Asks the server when nothing is stored, and never redirects. What a route guard wants, where login()
would navigate away.
searchPrincipals
Paginated, cancellable people picker. fetchPrincipalList targets a different endpoint and cannot do it.
Document upload containers
The API v2 container endpoints, with their 409 while indexing contract.
aggregationCounts
Declare the administrator's page size per aggregation so $hasMore is computed against the real one
instead of the default 10.
What is not on this list
No endpoint was removed. No response shape changed. No configuration key was renamed. If something stopped working across the upgrade and it is not on this page, it is worth reporting rather than working around — see Errors for how to capture enough detail to make that report useful.