SharePoint Framework
Routing every request through the host's AadHttpClient, so a web part is authenticated by SharePoint rather than asking for a password.
Inside a SharePoint Framework web part, requests must travel through the host's AadHttpClient — that is what
attaches the Azure AD token. A plain fetch leaves without one, the server answers anonymously, and your web
part ends up showing a login form in a page the user is already signed into.
Import from the ./spfx subpath, which re-exports everything from the root plus the SharePoint transport.
npm install @microsoft/sp-http --save-peerWiring the transport
Two ways, and the second is the one to prefer in new code.
import { createAtomicClient, createSpfxHttpAdapter } from "@sinequa/atomic/spfx";
import type { AtomicClient } from "@sinequa/atomic";
/**
* The type the SharePoint SDK provides. Declared here so the example stands alone;
* in a real web part it comes from `@microsoft/sp-http`.
*/
type AadHttpClientFactoryLike = {
getClient(resource: string): Promise<never>;
};
export class SearchWebPart {
private client?: AtomicClient;
/** Called from the web part's onInit(). */
async initialize(factory: AadHttpClientFactoryLike, resource: string) {
const aad = await factory.getClient(resource);
// Explicit transport: the client routes every request through it, so the
// Azure AD token is attached and no password is ever asked for.
this.client = createAtomicClient({
app: "<your-app>",
backendUrl: resource,
httpAdapter: createSpfxHttpAdapter(aad),
});
await this.client.initializeConfig();
await this.client.auth.login();
}
search(text: string) {
if (!this.client) throw new Error("initialize() was not awaited.");
return this.client.api.query.search({ name: "<your-query>", text, pageSize: 10 });
}
}import { InjectionToken } from "@angular/core";
import { createAtomicClient, createSpfxHttpAdapter } from "@sinequa/atomic/spfx";
import type { AtomicClient } from "@sinequa/atomic";
/**
* The SharePoint client, handed in by the web part that hosts this application.
* Declared as a minimal shape so the example stands alone.
*/
type AadHttpClientLikeShape = { constructor: unknown };
let host: { client: unknown; resource: string } | undefined;
/** Called by the web part before bootstrapping Angular. */
export function setSpfxHost(client: unknown, resource: string) {
host = { client, resource };
}
export const SINEQUA = new InjectionToken<AtomicClient>("Sinequa client", {
factory: () => {
if (!host) throw new Error("setSpfxHost() must run before bootstrap.");
return createAtomicClient({
app: "<your-app>",
backendUrl: host.resource,
// The transport carries the Azure AD token; without it the requests leave
// unauthenticated and the mode falls back to a credentials form.
httpAdapter: createSpfxHttpAdapter(host.client as AadHttpClientLikeShape as never),
});
},
});import { createAtomicClient, createSpfxHttpAdapter } from "@sinequa/atomic/spfx";
import type { AtomicClient } from "@sinequa/atomic";
let client: AtomicClient | undefined;
/**
* Called from the web part's onInit(), before rendering. `aad` is the
* AadHttpClient the SharePoint factory produced.
*/
export async function initialize(aad: unknown, resource: string) {
client = createAtomicClient({
app: "<your-app>",
backendUrl: resource,
// The transport carries the Azure AD token; without it the requests leave
// unauthenticated and the mode falls back to a credentials form.
httpAdapter: createSpfxHttpAdapter(aad as never),
});
await client.initializeConfig();
await client.auth.login();
return client;
}
export function sinequa(): AtomicClient {
if (!client) throw new Error("initialize() must be awaited before use.");
return client;
}The older, global form
initializeAadHttpClient(aad) registers the client globally, and every free function then routes through it:
import { fetchQuery, initializeAadHttpClient } from "@sinequa/atomic/spfx";
// In onInit()
initializeAadHttpClient(await context.aadHttpClientFactory.getClient(resource));
// Anywhere after that
const result = await fetchQuery({ name: "<your-query>", text: "hello" });
// In onDispose()
initializeAadHttpClient(null);It still works, and a client created without an explicit httpAdapter falls back to it — resolved per
request, so a host that registers late is still picked up. Prefer the explicit adapter: it is what a second
client targeting another AAD resource needs, and it makes the dependency visible.
What the transport changes
Prop
Type